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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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 1578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 #endif | 1589 #endif |
1590 | 1590 |
1591 | 1591 |
1592 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1592 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
1593 intptr_t argument_count, | 1593 intptr_t argument_count, |
1594 const Array& argument_names, | 1594 const Array& argument_names, |
1595 Label* failed, | 1595 Label* failed, |
1596 Label* match_found, | 1596 Label* match_found, |
1597 intptr_t deopt_id, | 1597 intptr_t deopt_id, |
1598 TokenPosition token_index, | 1598 TokenPosition token_index, |
1599 LocationSummary* locs) { | 1599 LocationSummary* locs, |
| 1600 bool complete) { |
1600 ASSERT(is_optimizing()); | 1601 ASSERT(is_optimizing()); |
1601 __ Comment("EmitTestAndCall"); | 1602 __ Comment("EmitTestAndCall"); |
1602 const Array& arguments_descriptor = | 1603 const Array& arguments_descriptor = |
1603 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, | 1604 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, |
1604 argument_names)); | 1605 argument_names)); |
1605 | 1606 |
1606 // Load receiver into R0. | 1607 // Load receiver into R0. |
1607 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); | 1608 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); |
1608 __ LoadObject(R4, arguments_descriptor); | 1609 __ LoadObject(R4, arguments_descriptor); |
1609 | 1610 |
1610 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; | 1611 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
1611 const intptr_t kNumChecks = ic_data.NumberOfChecks(); | 1612 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
1612 | 1613 |
1613 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1614 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
1614 | 1615 |
1615 Label after_smi_test; | 1616 Label after_smi_test; |
1616 __ tst(R0, Operand(kSmiTagMask)); | |
1617 if (kFirstCheckIsSmi) { | 1617 if (kFirstCheckIsSmi) { |
| 1618 __ tst(R0, Operand(kSmiTagMask)); |
1618 // Jump if receiver is not Smi. | 1619 // Jump if receiver is not Smi. |
1619 if (kNumChecks == 1) { | 1620 if (kNumChecks == 1) { |
1620 __ b(failed, NE); | 1621 __ b(failed, NE); |
1621 } else { | 1622 } else { |
1622 __ b(&after_smi_test, NE); | 1623 __ b(&after_smi_test, NE); |
1623 } | 1624 } |
1624 // Do not use the code from the function, but let the code be patched so | 1625 // Do not use the code from the function, but let the code be patched so |
1625 // that we can record the outgoing edges to other code. | 1626 // that we can record the outgoing edges to other code. |
1626 const Function& function = Function::ZoneHandle( | 1627 const Function& function = Function::ZoneHandle( |
1627 zone(), ic_data.GetTargetAt(0)); | 1628 zone(), ic_data.GetTargetAt(0)); |
1628 GenerateStaticDartCall(deopt_id, | 1629 GenerateStaticDartCall(deopt_id, |
1629 token_index, | 1630 token_index, |
1630 *StubCode::CallStaticFunction_entry(), | 1631 *StubCode::CallStaticFunction_entry(), |
1631 RawPcDescriptors::kOther, | 1632 RawPcDescriptors::kOther, |
1632 locs, | 1633 locs, |
1633 function); | 1634 function); |
1634 __ Drop(argument_count); | 1635 __ Drop(argument_count); |
1635 if (kNumChecks > 1) { | 1636 if (kNumChecks > 1) { |
1636 __ b(match_found); | 1637 __ b(match_found); |
1637 } | 1638 } |
1638 } else { | 1639 } else { |
1639 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1640 // Receiver is Smi, but Smi is not a valid class therefore fail. |
1640 // (Smi class must be first in the list). | 1641 // (Smi class must be first in the list). |
1641 __ b(failed, EQ); | 1642 if (!complete) { |
| 1643 __ tst(R0, Operand(kSmiTagMask)); |
| 1644 __ b(failed, EQ); |
| 1645 } |
1642 } | 1646 } |
1643 __ Bind(&after_smi_test); | 1647 __ Bind(&after_smi_test); |
1644 | 1648 |
1645 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1649 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
1646 GrowableArray<CidTarget> sorted(kNumChecks); | 1650 GrowableArray<CidTarget> sorted(kNumChecks); |
1647 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); | 1651 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); |
1648 | 1652 |
1649 // Value is not Smi, | 1653 // Value is not Smi, |
1650 const intptr_t kSortedLen = sorted.length(); | 1654 const intptr_t kSortedLen = sorted.length(); |
1651 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above | 1655 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above |
1652 // will fail if there was only one check and receiver is not Smi. | 1656 // will fail if there was only one check and receiver is not Smi. |
1653 if (kSortedLen == 0) return; | 1657 if (kSortedLen == 0) return; |
1654 | 1658 |
1655 __ LoadClassId(R2, R0); | 1659 __ LoadClassId(R2, R0); |
1656 for (intptr_t i = 0; i < kSortedLen; i++) { | 1660 for (intptr_t i = 0; i < kSortedLen; i++) { |
1657 const bool kIsLastCheck = (i == (kSortedLen - 1)); | 1661 const bool kIsLastCheck = (i == (kSortedLen - 1)); |
1658 ASSERT(sorted[i].cid != kSmiCid); | 1662 ASSERT(sorted[i].cid != kSmiCid); |
1659 Label next_test; | 1663 Label next_test; |
1660 __ CompareImmediate(R2, sorted[i].cid); | 1664 if (!complete) { |
1661 if (kIsLastCheck) { | 1665 __ CompareImmediate(R2, sorted[i].cid); |
1662 __ b(failed, NE); | 1666 if (kIsLastCheck) { |
| 1667 __ b(failed, NE); |
| 1668 } else { |
| 1669 __ b(&next_test, NE); |
| 1670 } |
1663 } else { | 1671 } else { |
1664 __ b(&next_test, NE); | 1672 if (!kIsLastCheck) { |
| 1673 __ CompareImmediate(R2, sorted[i].cid); |
| 1674 __ b(&next_test, NE); |
| 1675 } |
1665 } | 1676 } |
1666 // Do not use the code from the function, but let the code be patched so | 1677 // Do not use the code from the function, but let the code be patched so |
1667 // that we can record the outgoing edges to other code. | 1678 // that we can record the outgoing edges to other code. |
1668 const Function& function = *sorted[i].target; | 1679 const Function& function = *sorted[i].target; |
1669 GenerateStaticDartCall(deopt_id, | 1680 GenerateStaticDartCall(deopt_id, |
1670 token_index, | 1681 token_index, |
1671 *StubCode::CallStaticFunction_entry(), | 1682 *StubCode::CallStaticFunction_entry(), |
1672 RawPcDescriptors::kOther, | 1683 RawPcDescriptors::kOther, |
1673 locs, | 1684 locs, |
1674 function); | 1685 function); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 DRegister dreg = EvenDRegisterOf(reg); | 1988 DRegister dreg = EvenDRegisterOf(reg); |
1978 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1989 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
1979 } | 1990 } |
1980 | 1991 |
1981 | 1992 |
1982 #undef __ | 1993 #undef __ |
1983 | 1994 |
1984 } // namespace dart | 1995 } // namespace dart |
1985 | 1996 |
1986 #endif // defined TARGET_ARCH_ARM | 1997 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |