| 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 |