| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |