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

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

Issue 2734883002: ICData::NumberOfChecks is O(n) so don't call it in loops (Closed)
Patch Set: Add const Created 3 years, 9 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/code_generator.cc » ('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 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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/code_generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698