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 |