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

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

Issue 2829603002: Fall back to megamorphic stub when dispatching calls to rare classes. (Closed)
Patch Set: Added comment and used call site deopt history to control Created 3 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 | runtime/vm/object.h » ('j') | 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 #ifndef DART_PRECOMPILED_RUNTIME 4 #ifndef DART_PRECOMPILED_RUNTIME
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 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 } 1542 }
1543 1543
1544 if (Token::IsTypeCastOperator(op_kind)) { 1544 if (Token::IsTypeCastOperator(op_kind)) {
1545 ReplaceWithTypeCast(instr); 1545 ReplaceWithTypeCast(instr);
1546 return; 1546 return;
1547 } 1547 }
1548 1548
1549 const ICData& unary_checks = 1549 const ICData& unary_checks =
1550 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); 1550 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
1551 1551
1552 const bool is_dense = CheckClassInstr::IsDenseCidRange(unary_checks);
1553 const intptr_t number_of_checks = unary_checks.NumberOfChecks();
1554 if (op_kind == Token::kEQ &&
1555 number_of_checks > FLAG_max_equality_polymorphic_checks && !is_dense &&
1556 flow_graph()->InstanceCallNeedsClassCheck(
1557 instr, RawFunction::kRegularFunction)) {
1558 // Too many checks, it will be megamorphic which needs unary checks.
1559 instr->set_ic_data(&unary_checks);
1560 return;
1561 }
1562
1563 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { 1552 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
1564 return; 1553 return;
1565 } 1554 }
1566 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { 1555 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
1567 return; 1556 return;
1568 } 1557 }
1569 1558
1570 if (op_kind == Token::kEQ && TryReplaceWithEqualityOp(instr, op_kind)) { 1559 if (op_kind == Token::kEQ && TryReplaceWithEqualityOp(instr, op_kind)) {
1571 return; 1560 return;
1572 } 1561 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { 1610 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) {
1622 PolymorphicInstanceCallInstr* call = 1611 PolymorphicInstanceCallInstr* call =
1623 new (Z) PolymorphicInstanceCallInstr(instr, unary_checks, 1612 new (Z) PolymorphicInstanceCallInstr(instr, unary_checks,
1624 /* call_with_checks = */ false, 1613 /* call_with_checks = */ false,
1625 /* complete = */ false); 1614 /* complete = */ false);
1626 instr->ReplaceWith(call, current_iterator()); 1615 instr->ReplaceWith(call, current_iterator());
1627 return; 1616 return;
1628 } 1617 }
1629 } 1618 }
1630 1619
1620 // If there is only one target we can make this into a deopting class check,
1621 // followed by a call instruction that does not check the class of the
1622 // receiver. This enables a lot of optimizations because after the class
1623 // check we can probably inline the call and not worry about side effects.
1624 // However, this can fall down if new receiver classes arrive at this call
1625 // site after we generated optimized code. This causes a deopt, and after a
1626 // few deopts we won't optimize this function any more at all. Therefore for
1627 // very polymorphic sites we don't make this optimization, keeping it as a
1628 // regular checked PolymorphicInstanceCall, which falls back to the slow but
1629 // non-deopting megamorphic call stub when it sees new receiver classes.
1631 bool call_with_checks; 1630 bool call_with_checks;
1632 if (has_one_target && FLAG_polymorphic_with_deopt) { 1631 if (has_one_target && FLAG_polymorphic_with_deopt &&
1632 (!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) ||
1633 unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
1633 // Type propagation has not run yet, we cannot eliminate the check. 1634 // Type propagation has not run yet, we cannot eliminate the check.
1634 AddReceiverCheck(instr); 1635 AddReceiverCheck(instr);
1635 // Call can still deoptimize, do not detach environment from instr. 1636 // Call can still deoptimize, do not detach environment from instr.
1636 call_with_checks = false; 1637 call_with_checks = false;
1637 } else { 1638 } else {
1638 call_with_checks = true; 1639 call_with_checks = true;
1639 } 1640 }
1640 PolymorphicInstanceCallInstr* call = new (Z) 1641 PolymorphicInstanceCallInstr* call = new (Z)
1641 PolymorphicInstanceCallInstr(instr, unary_checks, call_with_checks, 1642 PolymorphicInstanceCallInstr(instr, unary_checks, call_with_checks,
1642 /* complete = */ false); 1643 /* complete = */ false);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 // Discard the environment from the original instruction because the store 1888 // Discard the environment from the original instruction because the store
1888 // can't deoptimize. 1889 // can't deoptimize.
1889 instr->RemoveEnvironment(); 1890 instr->RemoveEnvironment();
1890 ReplaceCall(instr, store); 1891 ReplaceCall(instr, store);
1891 return true; 1892 return true;
1892 } 1893 }
1893 1894
1894 1895
1895 } // namespace dart 1896 } // namespace dart
1896 #endif // DART_PRECOMPILED_RUNTIME 1897 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698