| 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/flow_graph_builder.h" | 7 #include "vm/flow_graph_builder.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 | 10 |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 TryReplaceWithBinaryOp(instr, comp, op_kind)) { | 379 TryReplaceWithBinaryOp(instr, comp, op_kind)) { |
| 380 return; | 380 return; |
| 381 } | 381 } |
| 382 if (Token::IsUnaryToken(op_kind) && | 382 if (Token::IsUnaryToken(op_kind) && |
| 383 TryReplaceWithUnaryOp(instr, comp, op_kind)) { | 383 TryReplaceWithUnaryOp(instr, comp, op_kind)) { |
| 384 return; | 384 return; |
| 385 } | 385 } |
| 386 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) { | 386 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) { |
| 387 return; | 387 return; |
| 388 } | 388 } |
| 389 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) { |
| 390 return; |
| 391 } |
| 389 if (TryInlineInstanceMethod(instr, comp)) { | 392 if (TryInlineInstanceMethod(instr, comp)) { |
| 390 return; | 393 return; |
| 391 } | 394 } |
| 392 const intptr_t kMaxChecks = 4; | 395 const intptr_t kMaxChecks = 4; |
| 393 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { | 396 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { |
| 394 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); | 397 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
| 395 ICData& unary_checks = | 398 ICData& unary_checks = |
| 396 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | 399 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 397 call->set_ic_data(&unary_checks); | 400 call->set_ic_data(&unary_checks); |
| 398 instr->set_computation(call); | 401 instr->set_computation(call); |
| 399 } | 402 } |
| 400 } | 403 } |
| 401 // An instance call without ICData should continue calling via IC calls | 404 // An instance call without ICData should continue calling via IC calls |
| 402 // which should trigger reoptimization of optimized code. | 405 // which should trigger reoptimization of optimized code. |
| 403 } | 406 } |
| 404 | 407 |
| 405 | 408 |
| 406 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp, | 409 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp, |
| 407 BindInstr* instr) { | 410 BindInstr* instr) { |
| 408 MethodRecognizer::Kind recognized_kind = | 411 MethodRecognizer::Kind recognized_kind = |
| 409 MethodRecognizer::RecognizeKind(comp->function()); | 412 MethodRecognizer::RecognizeKind(comp->function()); |
| 410 if (recognized_kind == MethodRecognizer::kMathSqrt) { | 413 if (recognized_kind == MethodRecognizer::kMathSqrt) { |
| 411 comp->set_recognized(MethodRecognizer::kMathSqrt); | 414 comp->set_recognized(MethodRecognizer::kMathSqrt); |
| 412 } | 415 } |
| 413 } | 416 } |
| 414 | 417 |
| 415 | 418 |
| 416 bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr, | 419 bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr, |
| 417 InstanceSetterComp* comp) { | 420 InstanceCallComp* comp) { |
| 421 if (FLAG_enable_type_checks) { |
| 422 // TODO(srdjan): Add assignable check node if --enable_type_checks. |
| 423 return false; |
| 424 } |
| 425 |
| 418 ASSERT(comp->HasICData()); | 426 ASSERT(comp->HasICData()); |
| 419 const ICData& ic_data = *comp->ic_data(); | 427 const ICData& ic_data = *comp->ic_data(); |
| 420 if (ic_data.NumberOfChecks() == 0) { | 428 if (ic_data.NumberOfChecks() == 0) { |
| 421 // No type feedback collected. | 429 // No type feedback collected. |
| 422 return false; | 430 return false; |
| 423 } | 431 } |
| 424 if (!HasOneTarget(ic_data)) { | 432 if (!HasOneTarget(ic_data)) { |
| 425 // TODO(srdjan): Implement when not all targets are the same. | 433 // TODO(srdjan): Implement when not all targets are the same. |
| 426 return false; | 434 return false; |
| 427 } | 435 } |
| 428 Function& target = Function::Handle(); | 436 Function& target = Function::Handle(); |
| 429 intptr_t class_id; | 437 intptr_t class_id; |
| 430 ic_data.GetOneClassCheckAt(0, &class_id, &target); | 438 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 431 if (target.kind() != RawFunction::kImplicitSetter) { | 439 if (target.kind() != RawFunction::kImplicitSetter) { |
| 432 // Not an implicit setter. | 440 // Not an implicit setter. |
| 433 // TODO(srdjan): Inline special setters. | 441 // TODO(srdjan): Inline special setters. |
| 434 return false; | 442 return false; |
| 435 } | 443 } |
| 436 // Inline implicit instance setter. | 444 // Inline implicit instance setter. |
| 437 const Field& field = Field::Handle(GetField(class_id, comp->field_name())); | 445 const String& field_name = |
| 446 String::Handle(Field::NameFromSetter(comp->function_name())); |
| 447 const Field& field = Field::Handle(GetField(class_id, field_name)); |
| 438 ASSERT(!field.IsNull()); | 448 ASSERT(!field.IsNull()); |
| 439 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( | 449 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( |
| 440 field, | 450 field, |
| 441 comp->ArgumentAt(0)->value(), | 451 comp->ArgumentAt(0)->value(), |
| 442 comp->ArgumentAt(1)->value(), | 452 comp->ArgumentAt(1)->value(), |
| 443 comp); | 453 comp); |
| 444 store->set_ic_data(comp->ic_data()); | 454 store->set_ic_data(comp->ic_data()); |
| 445 instr->set_computation(store); | 455 instr->set_computation(store); |
| 446 // Remove original push arguments. | 456 RemovePushArguments(comp); |
| 447 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { | |
| 448 comp->ArgumentAt(i)->RemoveFromGraph(); | |
| 449 } | |
| 450 return true; | 457 return true; |
| 451 } | 458 } |
| 452 | 459 |
| 453 | 460 |
| 454 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp, | |
| 455 BindInstr* instr) { | |
| 456 // TODO(srdjan): Add assignable check node if --enable_type_checks. | |
| 457 if (comp->HasICData() && !FLAG_enable_type_checks) { | |
| 458 if (TryInlineInstanceSetter(instr, comp)) { | |
| 459 return; | |
| 460 } | |
| 461 } | |
| 462 // TODO(srdjan): Polymorphic dispatch to setters or deoptimize. | |
| 463 } | |
| 464 | |
| 465 | |
| 466 enum IndexedAccessType { | 461 enum IndexedAccessType { |
| 467 kIndexedLoad, | 462 kIndexedLoad, |
| 468 kIndexedStore | 463 kIndexedStore |
| 469 }; | 464 }; |
| 470 | 465 |
| 471 | 466 |
| 472 static intptr_t ReceiverClassId(Computation* comp) { | 467 static intptr_t ReceiverClassId(Computation* comp) { |
| 473 if (!comp->HasICData()) return kIllegalObjectKind; | 468 if (!comp->HasICData()) return kIllegalObjectKind; |
| 474 | 469 |
| 475 const ICData& ic_data = *comp->ic_data(); | 470 const ICData& ic_data = *comp->ic_data(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 } | 583 } |
| 589 } | 584 } |
| 590 } | 585 } |
| 591 | 586 |
| 592 | 587 |
| 593 void FlowGraphTypePropagator::PropagateTypes() { | 588 void FlowGraphTypePropagator::PropagateTypes() { |
| 594 VisitBlocks(); | 589 VisitBlocks(); |
| 595 } | 590 } |
| 596 | 591 |
| 597 } // namespace dart | 592 } // namespace dart |
| OLD | NEW |