| 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 | 4 |
| 5 #include "vm/aot_optimizer.h" | 5 #include "vm/aot_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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 } | 494 } |
| 495 return true; | 495 return true; |
| 496 } | 496 } |
| 497 | 497 |
| 498 | 498 |
| 499 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { | 499 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { |
| 500 // Check for monomorphic IC data. | 500 // Check for monomorphic IC data. |
| 501 if (!call->HasICData()) return false; | 501 if (!call->HasICData()) return false; |
| 502 const ICData& ic_data = | 502 const ICData& ic_data = |
| 503 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | 503 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 504 if (ic_data.NumberOfChecks() != 1) { | 504 if (!ic_data.NumberOfChecksIs(1)) { |
| 505 return false; | 505 return false; |
| 506 } | 506 } |
| 507 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 507 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 508 flow_graph_, current_iterator(), call); | 508 flow_graph_, current_iterator(), call); |
| 509 } | 509 } |
| 510 | 510 |
| 511 | 511 |
| 512 // Return true if d is a string of length one (a constant or result from | 512 // Return true if d is a string of length one (a constant or result from |
| 513 // from string-from-char-code instruction. | 513 // from string-from-char-code instruction. |
| 514 static bool IsLengthOneString(Definition* d) { | 514 static bool IsLengthOneString(Definition* d) { |
| (...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 // Unknown result. | 1296 // Unknown result. |
| 1297 return Bool::null(); | 1297 return Bool::null(); |
| 1298 } | 1298 } |
| 1299 } | 1299 } |
| 1300 | 1300 |
| 1301 const ClassTable& class_table = *isolate()->class_table(); | 1301 const ClassTable& class_table = *isolate()->class_table(); |
| 1302 Bool& prev = Bool::Handle(Z); | 1302 Bool& prev = Bool::Handle(Z); |
| 1303 Class& cls = Class::Handle(Z); | 1303 Class& cls = Class::Handle(Z); |
| 1304 | 1304 |
| 1305 bool results_differ = false; | 1305 bool results_differ = false; |
| 1306 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { | 1306 const intptr_t number_of_checks = ic_data.NumberOfChecks(); |
| 1307 for (int i = 0; i < number_of_checks; i++) { |
| 1307 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); | 1308 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
| 1308 if (cls.NumTypeArguments() > 0) { | 1309 if (cls.NumTypeArguments() > 0) { |
| 1309 return Bool::null(); | 1310 return Bool::null(); |
| 1310 } | 1311 } |
| 1311 // As of Dart 1.5, the Null type is a subtype of (and is more specific than) | 1312 // As of Dart 1.5, the Null type is a subtype of (and is more specific than) |
| 1312 // any type. However, we are checking instances here and not types. The | 1313 // any type. However, we are checking instances here and not types. The |
| 1313 // null instance is only an instance of Null, Object, and dynamic. | 1314 // null instance is only an instance of Null, Object, and dynamic. |
| 1314 const bool is_subtype = | 1315 const bool is_subtype = |
| 1315 cls.IsNullClass() | 1316 cls.IsNullClass() |
| 1316 ? (type_class.IsNullClass() || type_class.IsObjectClass() || | 1317 ? (type_class.IsNullClass() || type_class.IsObjectClass() || |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 } | 1553 } |
| 1553 call->RemoveEnvironment(); | 1554 call->RemoveEnvironment(); |
| 1554 ReplaceCall(call, new_call); | 1555 ReplaceCall(call, new_call); |
| 1555 copy->DeepCopyTo(Z, new_call); | 1556 copy->DeepCopyTo(Z, new_call); |
| 1556 return; | 1557 return; |
| 1557 } | 1558 } |
| 1558 } | 1559 } |
| 1559 | 1560 |
| 1560 const ICData& unary_checks = | 1561 const ICData& unary_checks = |
| 1561 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1562 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1562 if ((unary_checks.NumberOfChecks() > 0) && | 1563 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1563 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 1564 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { |
| 1564 ZoneGrowableArray<intptr_t>* results = | 1565 ZoneGrowableArray<intptr_t>* results = |
| 1565 new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 1566 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1566 InstanceOfAsBool(unary_checks, type, results); | 1567 InstanceOfAsBool(unary_checks, type, results); |
| 1567 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 1568 if (results->length() == number_of_checks * 2) { |
| 1568 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1569 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 1569 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { | 1570 if (can_deopt && !IsAllowedForInlining(call->deopt_id())) { |
| 1570 // Guard against repeated speculative inlining. | 1571 // Guard against repeated speculative inlining. |
| 1571 return; | 1572 return; |
| 1572 } | 1573 } |
| 1573 TestCidsInstr* test_cids = new (Z) | 1574 TestCidsInstr* test_cids = new (Z) |
| 1574 TestCidsInstr(call->token_pos(), negate ? Token::kISNOT : Token::kIS, | 1575 TestCidsInstr(call->token_pos(), negate ? Token::kISNOT : Token::kIS, |
| 1575 new (Z) Value(left), *results, | 1576 new (Z) Value(left), *results, |
| 1576 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1577 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 1577 // Remove type. | 1578 // Remove type. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1590 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 1591 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 1591 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 1592 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 1592 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 1593 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 1593 Definition* left = call->ArgumentAt(0); | 1594 Definition* left = call->ArgumentAt(0); |
| 1594 Definition* type_args = call->ArgumentAt(1); | 1595 Definition* type_args = call->ArgumentAt(1); |
| 1595 const AbstractType& type = | 1596 const AbstractType& type = |
| 1596 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); | 1597 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
| 1597 ASSERT(!type.IsMalformedOrMalbounded()); | 1598 ASSERT(!type.IsMalformedOrMalbounded()); |
| 1598 const ICData& unary_checks = | 1599 const ICData& unary_checks = |
| 1599 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1600 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1600 if ((unary_checks.NumberOfChecks() > 0) && | 1601 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1601 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 1602 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) { |
| 1602 ZoneGrowableArray<intptr_t>* results = | 1603 ZoneGrowableArray<intptr_t>* results = |
| 1603 new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 1604 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1604 const Bool& as_bool = | 1605 const Bool& as_bool = |
| 1605 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 1606 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 1606 if (as_bool.raw() == Bool::True().raw()) { | 1607 if (as_bool.raw() == Bool::True().raw()) { |
| 1607 // Guard against repeated speculative inlining. | 1608 // Guard against repeated speculative inlining. |
| 1608 if (!IsAllowedForInlining(call->deopt_id())) { | 1609 if (!IsAllowedForInlining(call->deopt_id())) { |
| 1609 return; | 1610 return; |
| 1610 } | 1611 } |
| 1611 AddReceiverCheck(call); | 1612 AddReceiverCheck(call); |
| 1612 // Remove the original push arguments. | 1613 // Remove the original push arguments. |
| 1613 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 1614 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 | 1659 |
| 1659 | 1660 |
| 1660 bool AotOptimizer::TryInlineFieldAccess(InstanceCallInstr* call) { | 1661 bool AotOptimizer::TryInlineFieldAccess(InstanceCallInstr* call) { |
| 1661 const Token::Kind op_kind = call->token_kind(); | 1662 const Token::Kind op_kind = call->token_kind(); |
| 1662 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(call)) { | 1663 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(call)) { |
| 1663 return true; | 1664 return true; |
| 1664 } | 1665 } |
| 1665 | 1666 |
| 1666 const ICData& unary_checks = | 1667 const ICData& unary_checks = |
| 1667 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | 1668 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1668 if ((unary_checks.NumberOfChecks() > 0) && (op_kind == Token::kSET) && | 1669 if (!unary_checks.NumberOfChecksIs(0) && (op_kind == Token::kSET) && |
| 1669 TryInlineInstanceSetter(call, unary_checks)) { | 1670 TryInlineInstanceSetter(call, unary_checks)) { |
| 1670 return true; | 1671 return true; |
| 1671 } | 1672 } |
| 1672 | 1673 |
| 1673 return false; | 1674 return false; |
| 1674 } | 1675 } |
| 1675 | 1676 |
| 1676 | 1677 |
| 1677 // Tries to optimize instance call by replacing it with a faster instruction | 1678 // Tries to optimize instance call by replacing it with a faster instruction |
| 1678 // (e.g, binary op, field load, ..). | 1679 // (e.g, binary op, field load, ..). |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1699 if (RecognizeRuntimeTypeGetter(instr)) { | 1700 if (RecognizeRuntimeTypeGetter(instr)) { |
| 1700 return; | 1701 return; |
| 1701 } | 1702 } |
| 1702 | 1703 |
| 1703 if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) { | 1704 if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) { |
| 1704 return; | 1705 return; |
| 1705 } | 1706 } |
| 1706 | 1707 |
| 1707 const ICData& unary_checks = | 1708 const ICData& unary_checks = |
| 1708 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); | 1709 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); |
| 1709 if (IsAllowedForInlining(instr->deopt_id()) && | 1710 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1710 (unary_checks.NumberOfChecks() > 0)) { | 1711 if (IsAllowedForInlining(instr->deopt_id()) && number_of_checks > 0) { |
| 1711 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { | 1712 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { |
| 1712 return; | 1713 return; |
| 1713 } | 1714 } |
| 1714 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { | 1715 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { |
| 1715 return; | 1716 return; |
| 1716 } | 1717 } |
| 1717 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { | 1718 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { |
| 1718 return; | 1719 return; |
| 1719 } | 1720 } |
| 1720 | 1721 |
| 1721 if (Token::IsRelationalOperator(op_kind) && | 1722 if (Token::IsRelationalOperator(op_kind) && |
| 1722 TryReplaceWithRelationalOp(instr, op_kind)) { | 1723 TryReplaceWithRelationalOp(instr, op_kind)) { |
| 1723 return; | 1724 return; |
| 1724 } | 1725 } |
| 1725 | 1726 |
| 1726 if (Token::IsBinaryOperator(op_kind) && | 1727 if (Token::IsBinaryOperator(op_kind) && |
| 1727 TryReplaceWithBinaryOp(instr, op_kind)) { | 1728 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 1728 return; | 1729 return; |
| 1729 } | 1730 } |
| 1730 if (Token::IsUnaryOperator(op_kind) && | 1731 if (Token::IsUnaryOperator(op_kind) && |
| 1731 TryReplaceWithUnaryOp(instr, op_kind)) { | 1732 TryReplaceWithUnaryOp(instr, op_kind)) { |
| 1732 return; | 1733 return; |
| 1733 } | 1734 } |
| 1734 | 1735 |
| 1735 if (TryInlineInstanceMethod(instr)) { | 1736 if (TryInlineInstanceMethod(instr)) { |
| 1736 return; | 1737 return; |
| 1737 } | 1738 } |
| 1738 } | 1739 } |
| 1739 | 1740 |
| 1740 bool has_one_target = | 1741 bool has_one_target = number_of_checks > 0 && unary_checks.HasOneTarget(); |
| 1741 (unary_checks.NumberOfChecks() > 0) && unary_checks.HasOneTarget(); | |
| 1742 if (has_one_target) { | 1742 if (has_one_target) { |
| 1743 // Check if the single target is a polymorphic target, if it is, | 1743 // Check if the single target is a polymorphic target, if it is, |
| 1744 // we don't have one target. | 1744 // we don't have one target. |
| 1745 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1745 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); |
| 1746 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 1746 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
| 1747 has_one_target = !polymorphic_target; | 1747 has_one_target = !polymorphic_target; |
| 1748 } | 1748 } |
| 1749 | 1749 |
| 1750 if (has_one_target) { | 1750 if (has_one_target) { |
| 1751 RawFunction::Kind function_kind = | 1751 RawFunction::Kind function_kind = |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1925 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount()); | 1925 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount()); |
| 1926 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { | 1926 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { |
| 1927 args->Add(instr->PushArgumentAt(i)); | 1927 args->Add(instr->PushArgumentAt(i)); |
| 1928 } | 1928 } |
| 1929 StaticCallInstr* call = new (Z) StaticCallInstr( | 1929 StaticCallInstr* call = new (Z) StaticCallInstr( |
| 1930 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), | 1930 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), |
| 1931 instr->argument_names(), args, instr->deopt_id()); | 1931 instr->argument_names(), args, instr->deopt_id()); |
| 1932 instr->ReplaceWith(call, current_iterator()); | 1932 instr->ReplaceWith(call, current_iterator()); |
| 1933 return; | 1933 return; |
| 1934 } else if ((ic_data.raw() != ICData::null()) && | 1934 } else if ((ic_data.raw() != ICData::null()) && |
| 1935 (ic_data.NumberOfChecks() > 0)) { | 1935 !ic_data.NumberOfChecksIs(0)) { |
| 1936 PolymorphicInstanceCallInstr* call = | 1936 PolymorphicInstanceCallInstr* call = |
| 1937 new (Z) PolymorphicInstanceCallInstr(instr, ic_data, | 1937 new (Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| 1938 /* with_checks = */ true, | 1938 /* with_checks = */ true, |
| 1939 /* complete = */ true); | 1939 /* complete = */ true); |
| 1940 instr->ReplaceWith(call, current_iterator()); | 1940 instr->ReplaceWith(call, current_iterator()); |
| 1941 return; | 1941 return; |
| 1942 } | 1942 } |
| 1943 } | 1943 } |
| 1944 } | 1944 } |
| 1945 | 1945 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2014 case MethodRecognizer::kMathAtan: | 2014 case MethodRecognizer::kMathAtan: |
| 2015 case MethodRecognizer::kMathAtan2: | 2015 case MethodRecognizer::kMathAtan2: |
| 2016 FlowGraphInliner::TryReplaceStaticCallWithInline( | 2016 FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 2017 flow_graph_, current_iterator(), call); | 2017 flow_graph_, current_iterator(), call); |
| 2018 break; | 2018 break; |
| 2019 case MethodRecognizer::kMathMin: | 2019 case MethodRecognizer::kMathMin: |
| 2020 case MethodRecognizer::kMathMax: { | 2020 case MethodRecognizer::kMathMax: { |
| 2021 // We can handle only monomorphic min/max call sites with both arguments | 2021 // We can handle only monomorphic min/max call sites with both arguments |
| 2022 // being either doubles or smis. | 2022 // being either doubles or smis. |
| 2023 if (CanUnboxDouble() && call->HasICData() && | 2023 if (CanUnboxDouble() && call->HasICData() && |
| 2024 (call->ic_data()->NumberOfChecks() == 1)) { | 2024 call->ic_data()->NumberOfChecksIs(1)) { |
| 2025 const ICData& ic_data = *call->ic_data(); | 2025 const ICData& ic_data = *call->ic_data(); |
| 2026 intptr_t result_cid = kIllegalCid; | 2026 intptr_t result_cid = kIllegalCid; |
| 2027 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, | 2027 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, |
| 2028 kDoubleCid)) { | 2028 kDoubleCid)) { |
| 2029 result_cid = kDoubleCid; | 2029 result_cid = kDoubleCid; |
| 2030 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, | 2030 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, |
| 2031 kSmiCid)) { | 2031 kSmiCid)) { |
| 2032 result_cid = kSmiCid; | 2032 result_cid = kSmiCid; |
| 2033 } | 2033 } |
| 2034 if (result_cid != kIllegalCid) { | 2034 if (result_cid != kIllegalCid) { |
| 2035 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( | 2035 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( |
| 2036 recognized_kind, new (Z) Value(call->ArgumentAt(0)), | 2036 recognized_kind, new (Z) Value(call->ArgumentAt(0)), |
| 2037 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); | 2037 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); |
| 2038 const ICData& unary_checks = | 2038 const ICData& unary_checks = |
| 2039 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); | 2039 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); |
| 2040 AddCheckClass(min_max->left()->definition(), unary_checks, | 2040 AddCheckClass(min_max->left()->definition(), unary_checks, |
| 2041 call->deopt_id(), call->env(), call); | 2041 call->deopt_id(), call->env(), call); |
| 2042 AddCheckClass(min_max->right()->definition(), unary_checks, | 2042 AddCheckClass(min_max->right()->definition(), unary_checks, |
| 2043 call->deopt_id(), call->env(), call); | 2043 call->deopt_id(), call->env(), call); |
| 2044 ReplaceCall(call, min_max); | 2044 ReplaceCall(call, min_max); |
| 2045 } | 2045 } |
| 2046 } | 2046 } |
| 2047 break; | 2047 break; |
| 2048 } | 2048 } |
| 2049 case MethodRecognizer::kDoubleFromInteger: { | 2049 case MethodRecognizer::kDoubleFromInteger: { |
| 2050 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 2050 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { |
| 2051 const ICData& ic_data = *call->ic_data(); | 2051 const ICData& ic_data = *call->ic_data(); |
| 2052 if (CanUnboxDouble()) { | 2052 if (CanUnboxDouble()) { |
| 2053 if (ArgIsAlways(kSmiCid, ic_data, 1)) { | 2053 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
| 2054 Definition* arg = call->ArgumentAt(1); | 2054 Definition* arg = call->ArgumentAt(1); |
| 2055 AddCheckSmi(arg, call->deopt_id(), call->env(), call); | 2055 AddCheckSmi(arg, call->deopt_id(), call->env(), call); |
| 2056 ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg), | 2056 ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg), |
| 2057 call->token_pos())); | 2057 call->token_pos())); |
| 2058 } else if (ArgIsAlways(kMintCid, ic_data, 1) && | 2058 } else if (ArgIsAlways(kMintCid, ic_data, 1) && |
| 2059 CanConvertUnboxedMintToDouble()) { | 2059 CanConvertUnboxedMintToDouble()) { |
| 2060 Definition* arg = call->ArgumentAt(1); | 2060 Definition* arg = call->ArgumentAt(1); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2083 const ICData& unary_ic_data) { | 2083 const ICData& unary_ic_data) { |
| 2084 ASSERT((unary_ic_data.NumberOfChecks() > 0) && | 2084 ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
| 2085 (unary_ic_data.NumArgsTested() == 1)); | 2085 (unary_ic_data.NumArgsTested() == 1)); |
| 2086 if (I->type_checks()) { | 2086 if (I->type_checks()) { |
| 2087 // Checked mode setters are inlined like normal methods by conventional | 2087 // Checked mode setters are inlined like normal methods by conventional |
| 2088 // inlining. | 2088 // inlining. |
| 2089 return false; | 2089 return false; |
| 2090 } | 2090 } |
| 2091 | 2091 |
| 2092 ASSERT(instr->HasICData()); | 2092 ASSERT(instr->HasICData()); |
| 2093 if (unary_ic_data.NumberOfChecks() == 0) { | 2093 if (unary_ic_data.NumberOfChecksIs(0)) { |
| 2094 // No type feedback collected. | 2094 // No type feedback collected. |
| 2095 return false; | 2095 return false; |
| 2096 } | 2096 } |
| 2097 if (!unary_ic_data.HasOneTarget()) { | 2097 if (!unary_ic_data.HasOneTarget()) { |
| 2098 // Polymorphic sites are inlined like normal method calls by conventional | 2098 // Polymorphic sites are inlined like normal method calls by conventional |
| 2099 // inlining. | 2099 // inlining. |
| 2100 return false; | 2100 return false; |
| 2101 } | 2101 } |
| 2102 Function& target = Function::Handle(Z); | 2102 Function& target = Function::Handle(Z); |
| 2103 intptr_t class_id; | 2103 intptr_t class_id; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2149 FlowGraph::kEffect); | 2149 FlowGraph::kEffect); |
| 2150 current_iterator()->RemoveCurrentFromGraph(); | 2150 current_iterator()->RemoveCurrentFromGraph(); |
| 2151 } | 2151 } |
| 2152 } | 2152 } |
| 2153 } | 2153 } |
| 2154 } | 2154 } |
| 2155 | 2155 |
| 2156 #endif // DART_PRECOMPILER | 2156 #endif // DART_PRECOMPILER |
| 2157 | 2157 |
| 2158 } // namespace dart | 2158 } // namespace dart |
| OLD | NEW |