Chromium Code Reviews| 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 | 621 |
| 622 | 622 |
| 623 void FlowGraphCompiler::EmitComment(Instruction* instr) { | 623 void FlowGraphCompiler::EmitComment(Instruction* instr) { |
| 624 char buffer[256]; | 624 char buffer[256]; |
| 625 BufferFormatter f(buffer, sizeof(buffer)); | 625 BufferFormatter f(buffer, sizeof(buffer)); |
| 626 instr->PrintTo(&f); | 626 instr->PrintTo(&f); |
| 627 assembler()->Comment("%s", buffer); | 627 assembler()->Comment("%s", buffer); |
| 628 } | 628 } |
| 629 | 629 |
| 630 | 630 |
| 631 struct CidTarget { | |
| 632 intptr_t cid; | |
| 633 Function* target; | |
| 634 intptr_t count; | |
| 635 CidTarget(intptr_t cid_arg, | |
| 636 Function* target_arg, | |
| 637 intptr_t count_arg) | |
| 638 : cid(cid_arg), target(target_arg), count(count_arg) {} | |
| 639 }; | |
| 640 | |
| 641 | |
| 642 // Returns 'sorted' array in decreasing count order. | |
| 643 // The expected number of elements to sort is less than 10. | |
| 644 static void SortICDataByCount(const ICData& ic_data, | |
| 645 GrowableArray<CidTarget>* sorted) { | |
| 646 ASSERT(ic_data.num_args_tested() == 1); | |
| 647 const intptr_t len = ic_data.NumberOfChecks(); | |
| 648 sorted->Clear(); | |
| 649 | |
| 650 for (int i = 0; i < len; i++) { | |
| 651 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), | |
| 652 &Function::ZoneHandle(ic_data.GetTargetAt(i)), | |
| 653 ic_data.GetCountAt(i))); | |
| 654 } | |
| 655 for (int i = 0; i < len; i++) { | |
| 656 intptr_t largest_ix = i; | |
| 657 for (int k = i + 1; k < len; k++) { | |
| 658 if ((*sorted)[largest_ix].count < (*sorted)[k].count) { | |
|
regis
2012/12/27 17:52:30
You could assign (*sorted)[largest_ix].count to la
srdjan
2012/12/27 18:19:42
largest_ix is not loop invariant. Maintaining the
regis
2012/12/27 18:26:35
I do not disagree :-) Slow start after the break..
| |
| 659 largest_ix = k; | |
| 660 } | |
| 661 } | |
| 662 if (i != largest_ix) { | |
| 663 // Swap. | |
| 664 CidTarget temp = (*sorted)[i]; | |
| 665 (*sorted)[i] = (*sorted)[largest_ix]; | |
| 666 (*sorted)[largest_ix] = temp; | |
| 667 } | |
| 668 } | |
| 669 } | |
| 670 | |
| 671 | |
| 631 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 672 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| 632 Register class_id_reg, | 673 Register class_id_reg, |
| 633 intptr_t arg_count, | 674 intptr_t arg_count, |
| 634 const Array& arg_names, | 675 const Array& arg_names, |
| 635 Label* deopt, | 676 Label* deopt, |
| 636 intptr_t deopt_id, | 677 intptr_t deopt_id, |
| 637 intptr_t token_index, | 678 intptr_t token_index, |
| 638 LocationSummary* locs) { | 679 LocationSummary* locs) { |
| 639 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 680 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 640 Label match_found; | 681 Label match_found; |
| 641 const intptr_t len = ic_data.NumberOfChecks(); | 682 const intptr_t len = ic_data.NumberOfChecks(); |
| 683 GrowableArray<CidTarget> sorted(len); | |
| 684 SortICDataByCount(ic_data, &sorted); | |
| 642 for (intptr_t i = 0; i < len; i++) { | 685 for (intptr_t i = 0; i < len; i++) { |
| 643 const bool is_last_check = (i == (len - 1)); | 686 const bool is_last_check = (i == (len - 1)); |
| 644 Label next_test; | 687 Label next_test; |
| 645 assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i))); | 688 assembler()->cmpl(class_id_reg, Immediate(sorted[i].cid)); |
| 646 if (is_last_check) { | 689 if (is_last_check) { |
| 647 assembler()->j(NOT_EQUAL, deopt); | 690 assembler()->j(NOT_EQUAL, deopt); |
| 648 } else { | 691 } else { |
| 649 assembler()->j(NOT_EQUAL, &next_test); | 692 assembler()->j(NOT_EQUAL, &next_test); |
| 650 } | 693 } |
| 651 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | |
| 652 GenerateStaticCall(deopt_id, | 694 GenerateStaticCall(deopt_id, |
| 653 token_index, | 695 token_index, |
| 654 target, | 696 *sorted[i].target, |
| 655 arg_count, | 697 arg_count, |
| 656 arg_names, | 698 arg_names, |
| 657 locs); | 699 locs); |
| 658 if (!is_last_check) { | 700 if (!is_last_check) { |
| 659 assembler()->jmp(&match_found); | 701 assembler()->jmp(&match_found); |
| 660 } | 702 } |
| 661 assembler()->Bind(&next_test); | 703 assembler()->Bind(&next_test); |
| 662 } | 704 } |
| 663 assembler()->Bind(&match_found); | 705 assembler()->Bind(&match_found); |
| 664 } | 706 } |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 const AbstractTypeArguments& type_arguments = | 1074 const AbstractTypeArguments& type_arguments = |
| 1033 AbstractTypeArguments::Handle(type.arguments()); | 1075 AbstractTypeArguments::Handle(type.arguments()); |
| 1034 const bool is_raw_type = type_arguments.IsNull() || | 1076 const bool is_raw_type = type_arguments.IsNull() || |
| 1035 type_arguments.IsRaw(type_arguments.Length()); | 1077 type_arguments.IsRaw(type_arguments.Length()); |
| 1036 return is_raw_type; | 1078 return is_raw_type; |
| 1037 } | 1079 } |
| 1038 return true; | 1080 return true; |
| 1039 } | 1081 } |
| 1040 | 1082 |
| 1041 } // namespace dart | 1083 } // namespace dart |
| OLD | NEW |