| 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 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType( | 1482 has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType( |
| 1483 targets) != Type::null(); | 1483 targets) != Type::null(); |
| 1484 } else { | 1484 } else { |
| 1485 const bool polymorphic_target = | 1485 const bool polymorphic_target = |
| 1486 MethodRecognizer::PolymorphicTarget(target); | 1486 MethodRecognizer::PolymorphicTarget(target); |
| 1487 has_one_target = !polymorphic_target; | 1487 has_one_target = !polymorphic_target; |
| 1488 } | 1488 } |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 if (has_one_target) { | 1491 if (has_one_target) { |
| 1492 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1492 const Function& target = |
| 1493 Function::ZoneHandle(Z, unary_checks.GetTargetAt(0)); |
| 1493 const RawFunction::Kind function_kind = target.kind(); | 1494 const RawFunction::Kind function_kind = target.kind(); |
| 1494 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { | 1495 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { |
| 1495 StaticCallInstr* call = StaticCallInstr::FromCall(Z, instr, target); | 1496 StaticCallInstr* call = StaticCallInstr::FromCall(Z, instr, target); |
| 1496 instr->ReplaceWith(call, current_iterator()); | 1497 instr->ReplaceWith(call, current_iterator()); |
| 1497 return; | 1498 return; |
| 1498 } | 1499 } |
| 1499 } | 1500 } |
| 1500 | 1501 |
| 1501 // If there is only one target we can make this into a deopting class check, | 1502 // If there is only one target we can make this into a deopting class check, |
| 1502 // followed by a call instruction that does not check the class of the | 1503 // followed by a call instruction that does not check the class of the |
| 1503 // receiver. This enables a lot of optimizations because after the class | 1504 // receiver. This enables a lot of optimizations because after the class |
| 1504 // check we can probably inline the call and not worry about side effects. | 1505 // check we can probably inline the call and not worry about side effects. |
| 1505 // However, this can fall down if new receiver classes arrive at this call | 1506 // However, this can fall down if new receiver classes arrive at this call |
| 1506 // site after we generated optimized code. This causes a deopt, and after a | 1507 // site after we generated optimized code. This causes a deopt, and after a |
| 1507 // few deopts we won't optimize this function any more at all. Therefore for | 1508 // few deopts we won't optimize this function any more at all. Therefore for |
| 1508 // very polymorphic sites we don't make this optimization, keeping it as a | 1509 // very polymorphic sites we don't make this optimization, keeping it as a |
| 1509 // regular checked PolymorphicInstanceCall, which falls back to the slow but | 1510 // regular checked PolymorphicInstanceCall, which falls back to the slow but |
| 1510 // non-deopting megamorphic call stub when it sees new receiver classes. | 1511 // non-deopting megamorphic call stub when it sees new receiver classes. |
| 1511 if (has_one_target && FLAG_polymorphic_with_deopt && | 1512 if (has_one_target && FLAG_polymorphic_with_deopt && |
| 1512 (!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) || | 1513 (!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) || |
| 1513 unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 1514 unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
| 1514 // Type propagation has not run yet, we cannot eliminate the check. | 1515 // Type propagation has not run yet, we cannot eliminate the check. |
| 1515 // TODO(erikcorry): The receiver check should use the off-heap targets | 1516 // TODO(erikcorry): The receiver check should use the off-heap targets |
| 1516 // array, not the IC array. | 1517 // array, not the IC array. |
| 1517 AddReceiverCheck(instr); | 1518 AddReceiverCheck(instr); |
| 1518 // Call can still deoptimize, do not detach environment from instr. | 1519 // Call can still deoptimize, do not detach environment from instr. |
| 1519 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1520 const Function& target = |
| 1521 Function::ZoneHandle(Z, unary_checks.GetTargetAt(0)); |
| 1520 StaticCallInstr* call = StaticCallInstr::FromCall(Z, instr, target); | 1522 StaticCallInstr* call = StaticCallInstr::FromCall(Z, instr, target); |
| 1521 instr->ReplaceWith(call, current_iterator()); | 1523 instr->ReplaceWith(call, current_iterator()); |
| 1522 } else { | 1524 } else { |
| 1523 PolymorphicInstanceCallInstr* call = | 1525 PolymorphicInstanceCallInstr* call = |
| 1524 new (Z) PolymorphicInstanceCallInstr(instr, targets, | 1526 new (Z) PolymorphicInstanceCallInstr(instr, targets, |
| 1525 /* complete = */ false); | 1527 /* complete = */ false); |
| 1526 instr->ReplaceWith(call, current_iterator()); | 1528 instr->ReplaceWith(call, current_iterator()); |
| 1527 } | 1529 } |
| 1528 } | 1530 } |
| 1529 | 1531 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 // Discard the environment from the original instruction because the store | 1772 // Discard the environment from the original instruction because the store |
| 1771 // can't deoptimize. | 1773 // can't deoptimize. |
| 1772 instr->RemoveEnvironment(); | 1774 instr->RemoveEnvironment(); |
| 1773 ReplaceCall(instr, store); | 1775 ReplaceCall(instr, store); |
| 1774 return true; | 1776 return true; |
| 1775 } | 1777 } |
| 1776 | 1778 |
| 1777 | 1779 |
| 1778 } // namespace dart | 1780 } // namespace dart |
| 1779 #endif // DART_PRECOMPILED_RUNTIME | 1781 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |