| 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/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 #endif | 1613 #endif |
| 1614 | 1614 |
| 1615 | 1615 |
| 1616 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1616 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| 1617 intptr_t argument_count, | 1617 intptr_t argument_count, |
| 1618 const Array& argument_names, | 1618 const Array& argument_names, |
| 1619 Label* failed, | 1619 Label* failed, |
| 1620 Label* match_found, | 1620 Label* match_found, |
| 1621 intptr_t deopt_id, | 1621 intptr_t deopt_id, |
| 1622 TokenPosition token_index, | 1622 TokenPosition token_index, |
| 1623 LocationSummary* locs) { | 1623 LocationSummary* locs, |
| 1624 bool complete) { |
| 1624 ASSERT(is_optimizing()); | 1625 ASSERT(is_optimizing()); |
| 1625 __ Comment("EmitTestAndCall"); | 1626 __ Comment("EmitTestAndCall"); |
| 1626 const Array& arguments_descriptor = | 1627 const Array& arguments_descriptor = |
| 1627 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, | 1628 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, |
| 1628 argument_names)); | 1629 argument_names)); |
| 1629 | 1630 |
| 1630 // Load receiver into T0. | 1631 // Load receiver into T0. |
| 1631 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); | 1632 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); |
| 1632 __ LoadObject(S4, arguments_descriptor); | 1633 __ LoadObject(S4, arguments_descriptor); |
| 1633 | 1634 |
| 1634 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; | 1635 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
| 1635 const intptr_t kNumChecks = ic_data.NumberOfChecks(); | 1636 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
| 1636 | 1637 |
| 1637 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1638 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
| 1638 | 1639 |
| 1639 Label after_smi_test; | 1640 Label after_smi_test; |
| 1640 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 1641 if (kFirstCheckIsSmi) { | 1641 if (kFirstCheckIsSmi) { |
| 1642 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 1642 // Jump if receiver is not Smi. | 1643 // Jump if receiver is not Smi. |
| 1643 if (kNumChecks == 1) { | 1644 if (kNumChecks == 1) { |
| 1644 __ bne(CMPRES1, ZR, failed); | 1645 __ bne(CMPRES1, ZR, failed); |
| 1645 } else { | 1646 } else { |
| 1646 __ bne(CMPRES1, ZR, &after_smi_test); | 1647 __ bne(CMPRES1, ZR, &after_smi_test); |
| 1647 } | 1648 } |
| 1648 // Do not use the code from the function, but let the code be patched so | 1649 // Do not use the code from the function, but let the code be patched so |
| 1649 // that we can record the outgoing edges to other code. | 1650 // that we can record the outgoing edges to other code. |
| 1650 const Function& function = Function::ZoneHandle( | 1651 const Function& function = Function::ZoneHandle( |
| 1651 zone(), ic_data.GetTargetAt(0)); | 1652 zone(), ic_data.GetTargetAt(0)); |
| 1652 GenerateStaticDartCall(deopt_id, | 1653 GenerateStaticDartCall(deopt_id, |
| 1653 token_index, | 1654 token_index, |
| 1654 *StubCode::CallStaticFunction_entry(), | 1655 *StubCode::CallStaticFunction_entry(), |
| 1655 RawPcDescriptors::kOther, | 1656 RawPcDescriptors::kOther, |
| 1656 locs, | 1657 locs, |
| 1657 function); | 1658 function); |
| 1658 __ Drop(argument_count); | 1659 __ Drop(argument_count); |
| 1659 if (kNumChecks > 1) { | 1660 if (kNumChecks > 1) { |
| 1660 __ b(match_found); | 1661 __ b(match_found); |
| 1661 } | 1662 } |
| 1662 } else { | 1663 } else { |
| 1663 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1664 // Receiver is Smi, but Smi is not a valid class therefore fail. |
| 1664 // (Smi class must be first in the list). | 1665 // (Smi class must be first in the list). |
| 1665 __ beq(CMPRES1, ZR, failed); | 1666 if (!complete) { |
| 1667 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 1668 __ beq(CMPRES1, ZR, failed); |
| 1669 } |
| 1666 } | 1670 } |
| 1667 | 1671 |
| 1668 __ Bind(&after_smi_test); | 1672 __ Bind(&after_smi_test); |
| 1669 | 1673 |
| 1670 GrowableArray<CidTarget> sorted(kNumChecks); | 1674 GrowableArray<CidTarget> sorted(kNumChecks); |
| 1671 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); | 1675 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); |
| 1672 | 1676 |
| 1673 // Value is not Smi, | 1677 // Value is not Smi, |
| 1674 const intptr_t kSortedLen = sorted.length(); | 1678 const intptr_t kSortedLen = sorted.length(); |
| 1675 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above | 1679 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above |
| 1676 // will fail if there was only one check and receiver is not Smi. | 1680 // will fail if there was only one check and receiver is not Smi. |
| 1677 if (kSortedLen == 0) return; | 1681 if (kSortedLen == 0) return; |
| 1678 | 1682 |
| 1679 __ LoadClassId(T2, T0); | 1683 __ LoadClassId(T2, T0); |
| 1680 for (intptr_t i = 0; i < kSortedLen; i++) { | 1684 for (intptr_t i = 0; i < kSortedLen; i++) { |
| 1681 const bool kIsLastCheck = (i == (kSortedLen - 1)); | 1685 const bool kIsLastCheck = (i == (kSortedLen - 1)); |
| 1682 ASSERT(sorted[i].cid != kSmiCid); | 1686 ASSERT(sorted[i].cid != kSmiCid); |
| 1683 Label next_test; | 1687 Label next_test; |
| 1684 if (kIsLastCheck) { | 1688 if (!complete) { |
| 1685 __ BranchNotEqual(T2, Immediate(sorted[i].cid), failed); | 1689 if (kIsLastCheck) { |
| 1690 __ BranchNotEqual(T2, Immediate(sorted[i].cid), failed); |
| 1691 } else { |
| 1692 __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test); |
| 1693 } |
| 1686 } else { | 1694 } else { |
| 1687 __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test); | 1695 if (!kIsLastCheck) { |
| 1696 __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test); |
| 1697 } |
| 1688 } | 1698 } |
| 1689 // Do not use the code from the function, but let the code be patched so | 1699 // Do not use the code from the function, but let the code be patched so |
| 1690 // that we can record the outgoing edges to other code. | 1700 // that we can record the outgoing edges to other code. |
| 1691 const Function& function = *sorted[i].target; | 1701 const Function& function = *sorted[i].target; |
| 1692 GenerateStaticDartCall(deopt_id, | 1702 GenerateStaticDartCall(deopt_id, |
| 1693 token_index, | 1703 token_index, |
| 1694 *StubCode::CallStaticFunction_entry(), | 1704 *StubCode::CallStaticFunction_entry(), |
| 1695 RawPcDescriptors::kOther, | 1705 RawPcDescriptors::kOther, |
| 1696 locs, | 1706 locs, |
| 1697 function); | 1707 function); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 __ AddImmediate(SP, kDoubleSize); | 1952 __ AddImmediate(SP, kDoubleSize); |
| 1943 } | 1953 } |
| 1944 | 1954 |
| 1945 | 1955 |
| 1946 #undef __ | 1956 #undef __ |
| 1947 | 1957 |
| 1948 | 1958 |
| 1949 } // namespace dart | 1959 } // namespace dart |
| 1950 | 1960 |
| 1951 #endif // defined TARGET_ARCH_MIPS | 1961 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |