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 |