| 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/hash_map.h" | 8 #include "vm/hash_map.h" |
| 9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 // TODO(srdjan): Implement for mutiple targets. | 359 // TODO(srdjan): Implement for mutiple targets. |
| 360 return false; | 360 return false; |
| 361 } | 361 } |
| 362 // Inline implicit instance getter. | 362 // Inline implicit instance getter. |
| 363 const String& field_name = | 363 const String& field_name = |
| 364 String::Handle(Field::NameFromGetter(comp->function_name())); | 364 String::Handle(Field::NameFromGetter(comp->function_name())); |
| 365 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); | 365 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); |
| 366 ASSERT(!field.IsNull()); | 366 ASSERT(!field.IsNull()); |
| 367 | 367 |
| 368 LoadInstanceFieldComp* load; | 368 LoadInstanceFieldComp* load; |
| 369 if (!use_ssa_) { | 369 // TODO(fschneider): Avoid generating redundant checks by checking the |
| 370 load = new LoadInstanceFieldComp(field, | 370 // result-cid of the value. |
| 371 comp->ArgumentAt(0)->value(), | 371 CheckClassComp* check = |
| 372 comp, | 372 new CheckClassComp(comp->ArgumentAt(0)->value(), comp); |
| 373 true); // Can deoptimize. | 373 const ICData& unary_checks = |
| 374 // TODO(fschneider): Remove the boolean parameter can_deoptimize once | 374 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 375 // the non-SSA optimizer is removed. | 375 check->set_ic_data(&unary_checks); |
| 376 load->set_ic_data(comp->ic_data()); | 376 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); |
| 377 } else { | 377 ASSERT(instr->env() != NULL); // Always the case with SSA. |
| 378 // TODO(fschneider): Avoid generating redundant checks by checking the | 378 // Attach the original environment to the check instruction. |
| 379 // result-cid of the value. | 379 check_instr->set_env(instr->env()); |
| 380 CheckClassComp* check = | 380 instr->set_env(NULL); |
| 381 new CheckClassComp(comp->ArgumentAt(0)->value(), comp); | 381 check_instr->InsertBefore(instr); |
| 382 const ICData& unary_checks = | 382 load = new LoadInstanceFieldComp(field, |
| 383 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | 383 comp->ArgumentAt(0)->value(), |
| 384 check->set_ic_data(&unary_checks); | 384 NULL, |
| 385 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); | 385 false); // Can not deoptimize. |
| 386 ASSERT(instr->env() != NULL); // Always the case with SSA. | |
| 387 // Attach the original environment to the check instruction. | |
| 388 check_instr->set_env(instr->env()); | |
| 389 instr->set_env(NULL); | |
| 390 check_instr->InsertBefore(instr); | |
| 391 load = new LoadInstanceFieldComp(field, | |
| 392 comp->ArgumentAt(0)->value(), | |
| 393 NULL, | |
| 394 false); // Can not deoptimize. | |
| 395 } | |
| 396 instr->set_computation(load); | 386 instr->set_computation(load); |
| 397 RemovePushArguments(comp); | 387 RemovePushArguments(comp); |
| 398 return true; | 388 return true; |
| 399 } | 389 } |
| 400 | 390 |
| 401 // Not an implicit getter. | 391 // Not an implicit getter. |
| 402 MethodRecognizer::Kind recognized_kind = | 392 MethodRecognizer::Kind recognized_kind = |
| 403 MethodRecognizer::RecognizeKind(target); | 393 MethodRecognizer::RecognizeKind(target); |
| 404 | 394 |
| 405 // VM objects length getter. | 395 // VM objects length getter. |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 } | 641 } |
| 652 | 642 |
| 653 | 643 |
| 654 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, | 644 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, |
| 655 BindInstr* instr) { | 645 BindInstr* instr) { |
| 656 if (FLAG_eliminate_type_checks && | 646 if (FLAG_eliminate_type_checks && |
| 657 !comp->is_eliminated() && | 647 !comp->is_eliminated() && |
| 658 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { | 648 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { |
| 659 // TODO(regis): Remove is_eliminated_ field and support. | 649 // TODO(regis): Remove is_eliminated_ field and support. |
| 660 comp->eliminate(); | 650 comp->eliminate(); |
| 661 if (is_ssa_) { | 651 |
| 662 UseVal* use = comp->value()->AsUse(); | 652 UseVal* use = comp->value()->AsUse(); |
| 663 ASSERT(use != NULL); | 653 ASSERT(use != NULL); |
| 664 Definition* result = use->definition(); | 654 Definition* result = use->definition(); |
| 665 ASSERT(result != NULL); | 655 ASSERT(result != NULL); |
| 666 // Replace uses and remove the current instructions via the iterator. | 656 // Replace uses and remove the current instructions via the iterator. |
| 667 instr->ReplaceUsesWith(result); | 657 instr->ReplaceUsesWith(result); |
| 668 ASSERT(current_iterator()->Current() == instr); | 658 ASSERT(current_iterator()->Current() == instr); |
| 669 current_iterator()->RemoveCurrentFromGraph(); | 659 current_iterator()->RemoveCurrentFromGraph(); |
| 670 if (FLAG_trace_optimization) { | 660 if (FLAG_trace_optimization) { |
| 671 OS::Print("Replacing v%d with v%d\n", | 661 OS::Print("Replacing v%d with v%d\n", |
| 672 instr->ssa_temp_index(), | 662 instr->ssa_temp_index(), |
| 673 result->ssa_temp_index()); | 663 result->ssa_temp_index()); |
| 674 } | |
| 675 } | 664 } |
| 665 |
| 676 if (FLAG_trace_type_check_elimination) { | 666 if (FLAG_trace_type_check_elimination) { |
| 677 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 667 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 678 comp->token_pos(), | 668 comp->token_pos(), |
| 679 comp->value(), | 669 comp->value(), |
| 680 comp->dst_type(), | 670 comp->dst_type(), |
| 681 comp->dst_name(), | 671 comp->dst_name(), |
| 682 comp->is_eliminated()); | 672 comp->is_eliminated()); |
| 683 } | 673 } |
| 684 } | 674 } |
| 685 } | 675 } |
| 686 | 676 |
| 687 | 677 |
| 688 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, | 678 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, |
| 689 BindInstr* instr) { | 679 BindInstr* instr) { |
| 690 // TODO(regis): Propagate NullType as well and revise the comment and code | 680 // TODO(regis): Propagate NullType as well and revise the comment and code |
| 691 // below to also eliminate the test for non-null and non-constant value. | 681 // below to also eliminate the test for non-null and non-constant value. |
| 692 | 682 |
| 693 // We can only eliminate an 'assert boolean' test when the checked value is | 683 // We can only eliminate an 'assert boolean' test when the checked value is |
| 694 // a constant time constant. Indeed, a variable of the proper compile time | 684 // a constant time constant. Indeed, a variable of the proper compile time |
| 695 // type (bool) may still hold null at run time and therefore fail the test. | 685 // type (bool) may still hold null at run time and therefore fail the test. |
| 696 if (FLAG_eliminate_type_checks && | 686 if (FLAG_eliminate_type_checks && |
| 697 !comp->is_eliminated() && | 687 !comp->is_eliminated() && |
| 698 comp->value()->BindsToConstant() && | 688 comp->value()->BindsToConstant() && |
| 699 !comp->value()->BindsToConstantNull() && | 689 !comp->value()->BindsToConstantNull() && |
| 700 comp->value()->CompileTypeIsMoreSpecificThan( | 690 comp->value()->CompileTypeIsMoreSpecificThan( |
| 701 Type::Handle(Type::BoolInterface()))) { | 691 Type::Handle(Type::BoolInterface()))) { |
| 702 // TODO(regis): Remove is_eliminated_ field and support. | 692 // TODO(regis): Remove is_eliminated_ field and support. |
| 703 comp->eliminate(); | 693 comp->eliminate(); |
| 704 if (is_ssa_) { | 694 |
| 705 UseVal* use = comp->value()->AsUse(); | 695 UseVal* use = comp->value()->AsUse(); |
| 706 ASSERT(use != NULL); | 696 ASSERT(use != NULL); |
| 707 Definition* result = use->definition(); | 697 Definition* result = use->definition(); |
| 708 ASSERT(result != NULL); | 698 ASSERT(result != NULL); |
| 709 // Replace uses and remove the current instructions via the iterator. | 699 // Replace uses and remove the current instructions via the iterator. |
| 710 instr->ReplaceUsesWith(result); | 700 instr->ReplaceUsesWith(result); |
| 711 ASSERT(current_iterator()->Current() == instr); | 701 ASSERT(current_iterator()->Current() == instr); |
| 712 current_iterator()->RemoveCurrentFromGraph(); | 702 current_iterator()->RemoveCurrentFromGraph(); |
| 713 if (FLAG_trace_optimization) { | 703 if (FLAG_trace_optimization) { |
| 714 OS::Print("Replacing v%d with v%d\n", | 704 OS::Print("Replacing v%d with v%d\n", |
| 715 instr->ssa_temp_index(), | 705 instr->ssa_temp_index(), |
| 716 result->ssa_temp_index()); | 706 result->ssa_temp_index()); |
| 717 } | |
| 718 } | 707 } |
| 708 |
| 719 if (FLAG_trace_type_check_elimination) { | 709 if (FLAG_trace_type_check_elimination) { |
| 720 const String& name = String::Handle(Symbols::New("boolean expression")); | 710 const String& name = String::Handle(Symbols::New("boolean expression")); |
| 721 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 711 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 722 comp->token_pos(), | 712 comp->token_pos(), |
| 723 comp->value(), | 713 comp->value(), |
| 724 Type::Handle(Type::BoolInterface()), | 714 Type::Handle(Type::BoolInterface()), |
| 725 name, | 715 name, |
| 726 comp->is_eliminated()); | 716 comp->is_eliminated()); |
| 727 } | 717 } |
| 728 } | 718 } |
| 729 } | 719 } |
| 730 | 720 |
| 731 | 721 |
| 732 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp, | 722 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp, |
| 733 BindInstr* instr) { | 723 BindInstr* instr) { |
| 734 // TODO(regis): Propagate NullType as well and revise the comment and code | 724 // TODO(regis): Propagate NullType as well and revise the comment and code |
| 735 // below to also eliminate the test for non-null and non-constant value. | 725 // below to also eliminate the test for non-null and non-constant value. |
| 736 | 726 |
| 737 // We can only eliminate an 'instance of' test when the checked value is | 727 // We can only eliminate an 'instance of' test when the checked value is |
| 738 // a constant time constant. Indeed, a variable of the proper compile time | 728 // a constant time constant. Indeed, a variable of the proper compile time |
| 739 // type may still hold null at run time and therefore fail the test. | 729 // type may still hold null at run time and therefore fail the test. |
| 740 // We do not bother checking for Object destination type, since the graph | 730 // We do not bother checking for Object destination type, since the graph |
| 741 // builder did already. | 731 // builder did already. |
| 742 if (FLAG_eliminate_type_checks && | 732 if (FLAG_eliminate_type_checks && |
| 743 comp->value()->BindsToConstant() && | 733 comp->value()->BindsToConstant() && |
| 744 !comp->value()->BindsToConstantNull() && | 734 !comp->value()->BindsToConstantNull() && |
| 745 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { | 735 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { |
| 746 if (is_ssa_) { | 736 UseVal* use = comp->value()->AsUse(); |
| 747 UseVal* use = comp->value()->AsUse(); | 737 ASSERT(use != NULL); |
| 748 ASSERT(use != NULL); | 738 Definition* result = use->definition(); |
| 749 Definition* result = use->definition(); | 739 ASSERT(result != NULL); |
| 750 ASSERT(result != NULL); | 740 // Replace uses and remove the current instructions via the iterator. |
| 751 // Replace uses and remove the current instructions via the iterator. | 741 instr->ReplaceUsesWith(result); |
| 752 instr->ReplaceUsesWith(result); | 742 ASSERT(current_iterator()->Current() == instr); |
| 753 ASSERT(current_iterator()->Current() == instr); | 743 current_iterator()->RemoveCurrentFromGraph(); |
| 754 current_iterator()->RemoveCurrentFromGraph(); | 744 if (FLAG_trace_optimization) { |
| 755 if (FLAG_trace_optimization) { | 745 OS::Print("Replacing v%d with v%d\n", |
| 756 OS::Print("Replacing v%d with v%d\n", | 746 instr->ssa_temp_index(), |
| 757 instr->ssa_temp_index(), | 747 result->ssa_temp_index()); |
| 758 result->ssa_temp_index()); | |
| 759 } | |
| 760 } | 748 } |
| 749 |
| 761 if (FLAG_trace_type_check_elimination) { | 750 if (FLAG_trace_type_check_elimination) { |
| 762 const String& name = String::Handle(Symbols::New("InstanceOf")); | 751 const String& name = String::Handle(Symbols::New("InstanceOf")); |
| 763 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 752 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 764 comp->token_pos(), | 753 comp->token_pos(), |
| 765 comp->value(), | 754 comp->value(), |
| 766 comp->type(), | 755 comp->type(), |
| 767 name, | 756 name, |
| 768 /* eliminated = */ true); | 757 /* eliminated = */ true); |
| 769 } | 758 } |
| 770 } | 759 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 OS::Print("Replacing v%d with v%d\n", | 930 OS::Print("Replacing v%d with v%d\n", |
| 942 instr->ssa_temp_index(), | 931 instr->ssa_temp_index(), |
| 943 result->ssa_temp_index()); | 932 result->ssa_temp_index()); |
| 944 } | 933 } |
| 945 } | 934 } |
| 946 } | 935 } |
| 947 } | 936 } |
| 948 | 937 |
| 949 | 938 |
| 950 } // namespace dart | 939 } // namespace dart |
| OLD | NEW |