Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: runtime/vm/jit_optimizer.cc

Issue 1847293002: VM: Improve single-target polymorphic calls. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: use kIntptrMax Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/jit_optimizer.h" 5 #include "vm/jit_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 2650 matching lines...) Expand 10 before | Expand all | Expand 10 after
2661 new(Z) AssertAssignableInstr(call->token_pos(), 2661 new(Z) AssertAssignableInstr(call->token_pos(),
2662 new(Z) Value(left), 2662 new(Z) Value(left),
2663 new(Z) Value(type_args), 2663 new(Z) Value(type_args),
2664 type, 2664 type,
2665 Symbols::InTypeCast(), 2665 Symbols::InTypeCast(),
2666 call->deopt_id()); 2666 call->deopt_id());
2667 ReplaceCall(call, assert_as); 2667 ReplaceCall(call, assert_as);
2668 } 2668 }
2669 2669
2670 2670
2671 static bool IsDenseCidRange(const ICData& unary_checks) {
Vyacheslav Egorov (Google) 2016/04/01 10:53:59 I am a bit concerned that we have two functions th
Florian Schneider 2016/04/01 15:58:43 Changed to use a single function CheckClassInstr::
2672 if (unary_checks.GetReceiverClassIdAt(0) == kSmiCid) return false;
2673 intptr_t max = 0;
2674 intptr_t min = kIntptrMax;
2675 for (intptr_t i = 0; i < unary_checks.NumberOfChecks(); ++i) {
2676 intptr_t cid = unary_checks.GetCidAt(i);
2677 if (cid < min) min = cid;
2678 if (cid > max) max = cid;
2679 }
2680 return (max - min) < kBitsPerWord;
2681 }
2682
2683
2671 // Tries to optimize instance call by replacing it with a faster instruction 2684 // Tries to optimize instance call by replacing it with a faster instruction
2672 // (e.g, binary op, field load, ..). 2685 // (e.g, binary op, field load, ..).
2673 void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 2686 void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
2674 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { 2687 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
2675 return; 2688 return;
2676 } 2689 }
2677 const Token::Kind op_kind = instr->token_kind(); 2690 const Token::Kind op_kind = instr->token_kind();
2678 2691
2679 // Type test is special as it always gets converted into inlined code. 2692 // Type test is special as it always gets converted into inlined code.
2680 if (Token::IsTypeTestOperator(op_kind)) { 2693 if (Token::IsTypeTestOperator(op_kind)) {
2681 ReplaceWithInstanceOf(instr); 2694 ReplaceWithInstanceOf(instr);
2682 return; 2695 return;
2683 } 2696 }
2684 2697
2685 if (Token::IsTypeCastOperator(op_kind)) { 2698 if (Token::IsTypeCastOperator(op_kind)) {
2686 ReplaceWithTypeCast(instr); 2699 ReplaceWithTypeCast(instr);
2687 return; 2700 return;
2688 } 2701 }
2689 2702
2690 const ICData& unary_checks = 2703 const ICData& unary_checks =
2691 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); 2704 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
2692 2705
2706 const bool is_dense = IsDenseCidRange(unary_checks);
2693 const intptr_t max_checks = (op_kind == Token::kEQ) 2707 const intptr_t max_checks = (op_kind == Token::kEQ)
2694 ? FLAG_max_equality_polymorphic_checks 2708 ? FLAG_max_equality_polymorphic_checks
2695 : FLAG_max_polymorphic_checks; 2709 : FLAG_max_polymorphic_checks;
2696 if ((unary_checks.NumberOfChecks() > max_checks) && 2710 if ((unary_checks.NumberOfChecks() > max_checks) &&
2711 !is_dense &&
2697 flow_graph()->InstanceCallNeedsClassCheck( 2712 flow_graph()->InstanceCallNeedsClassCheck(
2698 instr, RawFunction::kRegularFunction)) { 2713 instr, RawFunction::kRegularFunction)) {
2699 // Too many checks, it will be megamorphic which needs unary checks. 2714 // Too many checks, it will be megamorphic which needs unary checks.
2700 instr->set_ic_data(&unary_checks); 2715 instr->set_ic_data(&unary_checks);
2701 return; 2716 return;
2702 } 2717 }
2703 2718
2704 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { 2719 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
2705 return; 2720 return;
2706 } 2721 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2752 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); 2767 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind();
2753 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { 2768 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) {
2754 PolymorphicInstanceCallInstr* call = 2769 PolymorphicInstanceCallInstr* call =
2755 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 2770 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
2756 /* call_with_checks = */ false); 2771 /* call_with_checks = */ false);
2757 instr->ReplaceWith(call, current_iterator()); 2772 instr->ReplaceWith(call, current_iterator());
2758 return; 2773 return;
2759 } 2774 }
2760 } 2775 }
2761 2776
2762 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 2777 if ((unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) ||
2778 (has_one_target && is_dense)) {
2763 bool call_with_checks; 2779 bool call_with_checks;
2764 if (has_one_target && FLAG_polymorphic_with_deopt) { 2780 if (has_one_target && FLAG_polymorphic_with_deopt) {
2765 // Type propagation has not run yet, we cannot eliminate the check. 2781 // Type propagation has not run yet, we cannot eliminate the check.
2766 AddReceiverCheck(instr); 2782 AddReceiverCheck(instr);
2767 // Call can still deoptimize, do not detach environment from instr. 2783 // Call can still deoptimize, do not detach environment from instr.
2768 call_with_checks = false; 2784 call_with_checks = false;
2769 } else { 2785 } else {
2770 call_with_checks = true; 2786 call_with_checks = true;
2771 } 2787 }
2772 PolymorphicInstanceCallInstr* call = 2788 PolymorphicInstanceCallInstr* call =
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
3122 3138
3123 // Discard the environment from the original instruction because the store 3139 // Discard the environment from the original instruction because the store
3124 // can't deoptimize. 3140 // can't deoptimize.
3125 instr->RemoveEnvironment(); 3141 instr->RemoveEnvironment();
3126 ReplaceCall(instr, store); 3142 ReplaceCall(instr, store);
3127 return true; 3143 return true;
3128 } 3144 }
3129 3145
3130 3146
3131 } // namespace dart 3147 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698