| 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 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 431 } |
| 432 return true; | 432 return true; |
| 433 } | 433 } |
| 434 | 434 |
| 435 | 435 |
| 436 bool JitOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { | 436 bool JitOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { |
| 437 // Check for monomorphic IC data. | 437 // Check for monomorphic IC data. |
| 438 if (!call->HasICData()) return false; | 438 if (!call->HasICData()) return false; |
| 439 const ICData& ic_data = | 439 const ICData& ic_data = |
| 440 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | 440 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 441 if (ic_data.NumberOfChecks() != 1) { | 441 if (!ic_data.NumberOfChecksIs(1)) { |
| 442 return false; | 442 return false; |
| 443 } | 443 } |
| 444 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 444 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 445 flow_graph_, current_iterator(), call); | 445 flow_graph_, current_iterator(), call); |
| 446 } | 446 } |
| 447 | 447 |
| 448 | 448 |
| 449 // Return true if d is a string of length one (a constant or result from | 449 // Return true if d is a string of length one (a constant or result from |
| 450 // from string-from-char-code instruction. | 450 // from string-from-char-code instruction. |
| 451 static bool IsLengthOneString(Definition* d) { | 451 static bool IsLengthOneString(Definition* d) { |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 // Unknown result. | 1191 // Unknown result. |
| 1192 return Bool::null(); | 1192 return Bool::null(); |
| 1193 } | 1193 } |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 const ClassTable& class_table = *isolate()->class_table(); | 1196 const ClassTable& class_table = *isolate()->class_table(); |
| 1197 Bool& prev = Bool::Handle(Z); | 1197 Bool& prev = Bool::Handle(Z); |
| 1198 Class& cls = Class::Handle(Z); | 1198 Class& cls = Class::Handle(Z); |
| 1199 | 1199 |
| 1200 bool results_differ = false; | 1200 bool results_differ = false; |
| 1201 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { | 1201 const intptr_t number_of_checks = ic_data.NumberOfChecks(); |
| 1202 for (int i = 0; i < number_of_checks; i++) { |
| 1202 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); | 1203 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
| 1203 if (cls.NumTypeArguments() > 0) { | 1204 if (cls.NumTypeArguments() > 0) { |
| 1204 return Bool::null(); | 1205 return Bool::null(); |
| 1205 } | 1206 } |
| 1206 // As of Dart 1.5, the Null type is a subtype of (and is more specific than) | 1207 // As of Dart 1.5, the Null type is a subtype of (and is more specific than) |
| 1207 // any type. However, we are checking instances here and not types. The | 1208 // any type. However, we are checking instances here and not types. The |
| 1208 // null instance is only an instance of Null, Object, and dynamic. | 1209 // null instance is only an instance of Null, Object, and dynamic. |
| 1209 const bool is_subtype = | 1210 const bool is_subtype = |
| 1210 cls.IsNullClass() | 1211 cls.IsNullClass() |
| 1211 ? (type_class.IsNullClass() || type_class.IsObjectClass() || | 1212 ? (type_class.IsNullClass() || type_class.IsObjectClass() || |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 } else { | 1370 } else { |
| 1370 type_args = call->ArgumentAt(1); | 1371 type_args = call->ArgumentAt(1); |
| 1371 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); | 1372 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); |
| 1372 negate = | 1373 negate = |
| 1373 Bool::Cast( | 1374 Bool::Cast( |
| 1374 call->ArgumentAt(3)->OriginalDefinition()->AsConstant()->value()) | 1375 call->ArgumentAt(3)->OriginalDefinition()->AsConstant()->value()) |
| 1375 .value(); | 1376 .value(); |
| 1376 } | 1377 } |
| 1377 const ICData& unary_checks = | 1378 const ICData& unary_checks = |
| 1378 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1379 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1379 if ((unary_checks.NumberOfChecks() > 0) && | 1380 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1380 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 1381 if ((number_of_checks > 0) && |
| 1382 (number_of_checks <= FLAG_max_polymorphic_checks)) { |
| 1381 ZoneGrowableArray<intptr_t>* results = | 1383 ZoneGrowableArray<intptr_t>* results = |
| 1382 new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 1384 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1383 Bool& as_bool = | 1385 Bool& as_bool = |
| 1384 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 1386 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 1385 if (as_bool.IsNull()) { | 1387 if (as_bool.IsNull()) { |
| 1386 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 1388 if (results->length() == number_of_checks * 2) { |
| 1387 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1389 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 1388 TestCidsInstr* test_cids = new (Z) TestCidsInstr( | 1390 TestCidsInstr* test_cids = new (Z) TestCidsInstr( |
| 1389 call->token_pos(), negate ? Token::kISNOT : Token::kIS, | 1391 call->token_pos(), negate ? Token::kISNOT : Token::kIS, |
| 1390 new (Z) Value(left), *results, | 1392 new (Z) Value(left), *results, |
| 1391 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1393 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 1392 // Remove type. | 1394 // Remove type. |
| 1393 ReplaceCall(call, test_cids); | 1395 ReplaceCall(call, test_cids); |
| 1394 return; | 1396 return; |
| 1395 } | 1397 } |
| 1396 } else { | 1398 } else { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 1440 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 1439 void JitOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 1441 void JitOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 1440 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 1442 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 1441 Definition* left = call->ArgumentAt(0); | 1443 Definition* left = call->ArgumentAt(0); |
| 1442 Definition* type_args = call->ArgumentAt(1); | 1444 Definition* type_args = call->ArgumentAt(1); |
| 1443 const AbstractType& type = | 1445 const AbstractType& type = |
| 1444 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); | 1446 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
| 1445 ASSERT(!type.IsMalformedOrMalbounded()); | 1447 ASSERT(!type.IsMalformedOrMalbounded()); |
| 1446 const ICData& unary_checks = | 1448 const ICData& unary_checks = |
| 1447 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1449 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1448 if ((unary_checks.NumberOfChecks() > 0) && | 1450 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1449 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { | 1451 if ((number_of_checks > 0) && |
| 1452 (number_of_checks <= FLAG_max_polymorphic_checks)) { |
| 1450 ZoneGrowableArray<intptr_t>* results = | 1453 ZoneGrowableArray<intptr_t>* results = |
| 1451 new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 1454 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1452 const Bool& as_bool = | 1455 const Bool& as_bool = |
| 1453 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 1456 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 1454 if (as_bool.raw() == Bool::True().raw()) { | 1457 if (as_bool.raw() == Bool::True().raw()) { |
| 1455 AddReceiverCheck(call); | 1458 AddReceiverCheck(call); |
| 1456 // Remove the original push arguments. | 1459 // Remove the original push arguments. |
| 1457 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 1460 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 1458 PushArgumentInstr* push = call->PushArgumentAt(i); | 1461 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 1459 push->ReplaceUsesWith(push->value()->definition()); | 1462 push->ReplaceUsesWith(push->value()->definition()); |
| 1460 push->RemoveFromGraph(); | 1463 push->RemoveFromGraph(); |
| 1461 } | 1464 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1492 return; | 1495 return; |
| 1493 } | 1496 } |
| 1494 | 1497 |
| 1495 const ICData& unary_checks = | 1498 const ICData& unary_checks = |
| 1496 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); | 1499 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); |
| 1497 | 1500 |
| 1498 const bool is_dense = CheckClassInstr::IsDenseCidRange(unary_checks); | 1501 const bool is_dense = CheckClassInstr::IsDenseCidRange(unary_checks); |
| 1499 const intptr_t max_checks = (op_kind == Token::kEQ) | 1502 const intptr_t max_checks = (op_kind == Token::kEQ) |
| 1500 ? FLAG_max_equality_polymorphic_checks | 1503 ? FLAG_max_equality_polymorphic_checks |
| 1501 : FLAG_max_polymorphic_checks; | 1504 : FLAG_max_polymorphic_checks; |
| 1502 if ((unary_checks.NumberOfChecks() > max_checks) && !is_dense && | 1505 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1506 if ((number_of_checks > max_checks) && !is_dense && |
| 1503 flow_graph()->InstanceCallNeedsClassCheck( | 1507 flow_graph()->InstanceCallNeedsClassCheck( |
| 1504 instr, RawFunction::kRegularFunction)) { | 1508 instr, RawFunction::kRegularFunction)) { |
| 1505 // Too many checks, it will be megamorphic which needs unary checks. | 1509 // Too many checks, it will be megamorphic which needs unary checks. |
| 1506 instr->set_ic_data(&unary_checks); | 1510 instr->set_ic_data(&unary_checks); |
| 1507 return; | 1511 return; |
| 1508 } | 1512 } |
| 1509 | 1513 |
| 1510 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { | 1514 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { |
| 1511 return; | 1515 return; |
| 1512 } | 1516 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { | 1568 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { |
| 1565 PolymorphicInstanceCallInstr* call = | 1569 PolymorphicInstanceCallInstr* call = |
| 1566 new (Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 1570 new (Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 1567 /* call_with_checks = */ false, | 1571 /* call_with_checks = */ false, |
| 1568 /* complete = */ false); | 1572 /* complete = */ false); |
| 1569 instr->ReplaceWith(call, current_iterator()); | 1573 instr->ReplaceWith(call, current_iterator()); |
| 1570 return; | 1574 return; |
| 1571 } | 1575 } |
| 1572 } | 1576 } |
| 1573 | 1577 |
| 1574 if ((unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) || | 1578 if (number_of_checks <= FLAG_max_polymorphic_checks || |
| 1575 (has_one_target && is_dense)) { | 1579 (has_one_target && is_dense)) { |
| 1576 bool call_with_checks; | 1580 bool call_with_checks; |
| 1577 if (has_one_target && FLAG_polymorphic_with_deopt) { | 1581 if (has_one_target && FLAG_polymorphic_with_deopt) { |
| 1578 // Type propagation has not run yet, we cannot eliminate the check. | 1582 // Type propagation has not run yet, we cannot eliminate the check. |
| 1579 AddReceiverCheck(instr); | 1583 AddReceiverCheck(instr); |
| 1580 // Call can still deoptimize, do not detach environment from instr. | 1584 // Call can still deoptimize, do not detach environment from instr. |
| 1581 call_with_checks = false; | 1585 call_with_checks = false; |
| 1582 } else { | 1586 } else { |
| 1583 call_with_checks = true; | 1587 call_with_checks = true; |
| 1584 } | 1588 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 case MethodRecognizer::kMathAtan: | 1620 case MethodRecognizer::kMathAtan: |
| 1617 case MethodRecognizer::kMathAtan2: | 1621 case MethodRecognizer::kMathAtan2: |
| 1618 FlowGraphInliner::TryReplaceStaticCallWithInline( | 1622 FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 1619 flow_graph_, current_iterator(), call); | 1623 flow_graph_, current_iterator(), call); |
| 1620 break; | 1624 break; |
| 1621 case MethodRecognizer::kMathMin: | 1625 case MethodRecognizer::kMathMin: |
| 1622 case MethodRecognizer::kMathMax: { | 1626 case MethodRecognizer::kMathMax: { |
| 1623 // We can handle only monomorphic min/max call sites with both arguments | 1627 // We can handle only monomorphic min/max call sites with both arguments |
| 1624 // being either doubles or smis. | 1628 // being either doubles or smis. |
| 1625 if (CanUnboxDouble() && call->HasICData() && | 1629 if (CanUnboxDouble() && call->HasICData() && |
| 1626 (call->ic_data()->NumberOfChecks() == 1)) { | 1630 call->ic_data()->NumberOfChecksIs(1)) { |
| 1627 const ICData& ic_data = *call->ic_data(); | 1631 const ICData& ic_data = *call->ic_data(); |
| 1628 intptr_t result_cid = kIllegalCid; | 1632 intptr_t result_cid = kIllegalCid; |
| 1629 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, | 1633 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, |
| 1630 kDoubleCid)) { | 1634 kDoubleCid)) { |
| 1631 result_cid = kDoubleCid; | 1635 result_cid = kDoubleCid; |
| 1632 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, | 1636 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, |
| 1633 kSmiCid)) { | 1637 kSmiCid)) { |
| 1634 result_cid = kSmiCid; | 1638 result_cid = kSmiCid; |
| 1635 } | 1639 } |
| 1636 if (result_cid != kIllegalCid) { | 1640 if (result_cid != kIllegalCid) { |
| 1637 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( | 1641 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( |
| 1638 recognized_kind, new (Z) Value(call->ArgumentAt(0)), | 1642 recognized_kind, new (Z) Value(call->ArgumentAt(0)), |
| 1639 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); | 1643 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); |
| 1640 const ICData& unary_checks = | 1644 const ICData& unary_checks = |
| 1641 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); | 1645 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); |
| 1642 AddCheckClass(min_max->left()->definition(), unary_checks, | 1646 AddCheckClass(min_max->left()->definition(), unary_checks, |
| 1643 call->deopt_id(), call->env(), call); | 1647 call->deopt_id(), call->env(), call); |
| 1644 AddCheckClass(min_max->right()->definition(), unary_checks, | 1648 AddCheckClass(min_max->right()->definition(), unary_checks, |
| 1645 call->deopt_id(), call->env(), call); | 1649 call->deopt_id(), call->env(), call); |
| 1646 ReplaceCall(call, min_max); | 1650 ReplaceCall(call, min_max); |
| 1647 } | 1651 } |
| 1648 } | 1652 } |
| 1649 break; | 1653 break; |
| 1650 } | 1654 } |
| 1651 | 1655 |
| 1652 case MethodRecognizer::kDoubleFromInteger: { | 1656 case MethodRecognizer::kDoubleFromInteger: { |
| 1653 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 1657 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { |
| 1654 const ICData& ic_data = *call->ic_data(); | 1658 const ICData& ic_data = *call->ic_data(); |
| 1655 if (CanUnboxDouble()) { | 1659 if (CanUnboxDouble()) { |
| 1656 if (ArgIsAlways(kSmiCid, ic_data, 1)) { | 1660 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
| 1657 Definition* arg = call->ArgumentAt(1); | 1661 Definition* arg = call->ArgumentAt(1); |
| 1658 AddCheckSmi(arg, call->deopt_id(), call->env(), call); | 1662 AddCheckSmi(arg, call->deopt_id(), call->env(), call); |
| 1659 ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg), | 1663 ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg), |
| 1660 call->token_pos())); | 1664 call->token_pos())); |
| 1661 } else if (ArgIsAlways(kMintCid, ic_data, 1) && | 1665 } else if (ArgIsAlways(kMintCid, ic_data, 1) && |
| 1662 CanConvertUnboxedMintToDouble()) { | 1666 CanConvertUnboxedMintToDouble()) { |
| 1663 Definition* arg = call->ArgumentAt(1); | 1667 Definition* arg = call->ArgumentAt(1); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1762 void JitOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 1766 void JitOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 1763 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. | 1767 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. |
| 1764 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 1768 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
| 1765 if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedMint); | 1769 if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedMint); |
| 1766 #endif | 1770 #endif |
| 1767 } | 1771 } |
| 1768 | 1772 |
| 1769 | 1773 |
| 1770 bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, | 1774 bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
| 1771 const ICData& unary_ic_data) { | 1775 const ICData& unary_ic_data) { |
| 1772 ASSERT((unary_ic_data.NumberOfChecks() > 0) && | 1776 ASSERT(!unary_ic_data.NumberOfChecksIs(0) && |
| 1773 (unary_ic_data.NumArgsTested() == 1)); | 1777 (unary_ic_data.NumArgsTested() == 1)); |
| 1774 if (I->type_checks()) { | 1778 if (I->type_checks()) { |
| 1775 // Checked mode setters are inlined like normal methods by conventional | 1779 // Checked mode setters are inlined like normal methods by conventional |
| 1776 // inlining. | 1780 // inlining. |
| 1777 return false; | 1781 return false; |
| 1778 } | 1782 } |
| 1779 | 1783 |
| 1780 ASSERT(instr->HasICData()); | 1784 ASSERT(instr->HasICData()); |
| 1781 if (unary_ic_data.NumberOfChecks() == 0) { | 1785 if (unary_ic_data.NumberOfChecksIs(0)) { |
| 1782 // No type feedback collected. | 1786 // No type feedback collected. |
| 1783 return false; | 1787 return false; |
| 1784 } | 1788 } |
| 1785 if (!unary_ic_data.HasOneTarget()) { | 1789 if (!unary_ic_data.HasOneTarget()) { |
| 1786 // Polymorphic sites are inlined like normal method calls by conventional | 1790 // Polymorphic sites are inlined like normal method calls by conventional |
| 1787 // inlining. | 1791 // inlining. |
| 1788 return false; | 1792 return false; |
| 1789 } | 1793 } |
| 1790 Function& target = Function::Handle(Z); | 1794 Function& target = Function::Handle(Z); |
| 1791 intptr_t class_id; | 1795 intptr_t class_id; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 // Discard the environment from the original instruction because the store | 1837 // Discard the environment from the original instruction because the store |
| 1834 // can't deoptimize. | 1838 // can't deoptimize. |
| 1835 instr->RemoveEnvironment(); | 1839 instr->RemoveEnvironment(); |
| 1836 ReplaceCall(instr, store); | 1840 ReplaceCall(instr, store); |
| 1837 return true; | 1841 return true; |
| 1838 } | 1842 } |
| 1839 | 1843 |
| 1840 | 1844 |
| 1841 } // namespace dart | 1845 } // namespace dart |
| 1842 #endif // DART_PRECOMPILED_RUNTIME | 1846 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |