| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1574 // type feedback. | 1574 // type feedback. |
| 1575 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); | 1575 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); |
| 1576 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 1576 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 1577 | 1577 |
| 1578 __ Bind(&found); | 1578 __ Bind(&found); |
| 1579 // EBX: Pointer to an IC data check group. | 1579 // EBX: Pointer to an IC data check group. |
| 1580 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1580 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1581 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1581 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1582 __ movl(EAX, Address(EBX, target_offset)); | 1582 __ movl(EAX, Address(EBX, target_offset)); |
| 1583 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); | 1583 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 1584 __ j(NO_OVERFLOW, &call_target_function); | 1584 __ j(NO_OVERFLOW, &call_target_function, Assembler::kNearJump); |
| 1585 __ movl(Address(EBX, count_offset), | 1585 __ movl(Address(EBX, count_offset), |
| 1586 Immediate(Smi::RawValue(Smi::kMaxValue))); | 1586 Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1587 | 1587 |
| 1588 __ Bind(&call_target_function); | 1588 __ Bind(&call_target_function); |
| 1589 // EAX: Target function. | 1589 // EAX: Target function. |
| 1590 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 1590 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 1591 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1591 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1592 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1592 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1593 __ jmp(EAX); | 1593 __ jmp(EAX); |
| 1594 | 1594 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1673 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1674 } | 1674 } |
| 1675 | 1675 |
| 1676 | 1676 |
| 1677 // Megamorphic call is currently implemented as IC call but through a stub | 1677 // Megamorphic call is currently implemented as IC call but through a stub |
| 1678 // that does not check/count function invocations. | 1678 // that does not check/count function invocations. |
| 1679 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1679 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1680 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1680 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1681 } | 1681 } |
| 1682 | 1682 |
| 1683 // Intermediary stub between a static call and its target. ICData contains |
| 1684 // the target function and the call count. |
| 1685 // ECX: ICData |
| 1686 void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1687 GenerateUsageCounterIncrement(assembler, EBX); |
| 1688 #if defined(DEBUG) |
| 1689 { Label ok; |
| 1690 // Check that the IC data array has NumberOfArgumentsChecked() == 0. |
| 1691 // 'num_args_tested' is stored as an untagged int. |
| 1692 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1693 __ cmpl(EBX, Immediate(0)); |
| 1694 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1695 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1696 __ Bind(&ok); |
| 1697 } |
| 1698 #endif // DEBUG |
| 1699 |
| 1700 // ECX: IC data object (preserved). |
| 1701 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1702 // EBX: ic_data_array with entries: target functions and count. |
| 1703 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1704 // EBX: points directly to the first ic data array element. |
| 1705 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1706 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1707 |
| 1708 // Increment count for this call. |
| 1709 Label increment_done; |
| 1710 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 1711 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); |
| 1712 __ movl(Address(EBX, count_offset), Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1713 __ Bind(&increment_done); |
| 1714 |
| 1715 const Immediate& raw_null = |
| 1716 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1717 Label target_is_compiled; |
| 1718 // Get function and call it, if possible. |
| 1719 __ movl(EDI, Address(EBX, target_offset)); |
| 1720 __ movl(EAX, FieldAddress(EDI, Function::code_offset())); |
| 1721 __ cmpl(EAX, raw_null); |
| 1722 __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); |
| 1723 __ EnterStubFrame(); |
| 1724 __ pushl(EDI); // Preserve target function. |
| 1725 __ pushl(ECX); // Preserve IC data object. |
| 1726 __ pushl(EDI); // Pass function. |
| 1727 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| 1728 __ popl(EAX); // Discard argument. |
| 1729 __ popl(ECX); // Restore IC data object. |
| 1730 __ popl(EDI); // Restore target function. |
| 1731 __ LeaveFrame(); |
| 1732 __ movl(EAX, FieldAddress(EDI, Function::code_offset())); |
| 1733 |
| 1734 __ Bind(&target_is_compiled); |
| 1735 // EAX: Target code. |
| 1736 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1737 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1738 // Load arguments descriptor into EDX. |
| 1739 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1740 __ jmp(EAX); |
| 1741 } |
| 1742 |
| 1683 | 1743 |
| 1684 // EDX, EXC: May contain arguments to runtime stub. | 1744 // EDX, EXC: May contain arguments to runtime stub. |
| 1685 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1745 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1686 __ EnterStubFrame(); | 1746 __ EnterStubFrame(); |
| 1687 // Save runtime args. | 1747 // Save runtime args. |
| 1688 __ pushl(ECX); | 1748 __ pushl(ECX); |
| 1689 __ pushl(EDX); | 1749 __ pushl(EDX); |
| 1690 // Room for result. Debugger stub returns address of the | 1750 // Room for result. Debugger stub returns address of the |
| 1691 // unpatched runtime stub. | 1751 // unpatched runtime stub. |
| 1692 const Immediate& raw_null = | 1752 const Immediate& raw_null = |
| 1693 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1753 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1694 __ pushl(raw_null); // Room for result. | 1754 __ pushl(raw_null); // Room for result. |
| 1695 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry); | 1755 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry); |
| 1696 __ popl(EAX); // Address of original stub. | 1756 __ popl(EAX); // Address of original stub. |
| 1697 __ popl(EDX); // Restore arguments. | 1757 __ popl(EDX); // Restore arguments. |
| 1698 __ popl(ECX); | 1758 __ popl(ECX); |
| 1699 __ LeaveFrame(); | 1759 __ LeaveFrame(); |
| 1700 __ jmp(EAX); // Jump to original stub. | 1760 __ jmp(EAX); // Jump to original stub. |
| 1701 } | 1761 } |
| 1702 | 1762 |
| 1703 | 1763 |
| 1704 // EDX: Arguments descriptor array. | 1764 // ECX: ICData (unoptimized static call). |
| 1705 // TOS(0): return address (Dart code). | 1765 // TOS(0): return address (Dart code). |
| 1706 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1766 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1707 // Create a stub frame as we are pushing some objects on the stack before | 1767 // Create a stub frame as we are pushing some objects on the stack before |
| 1708 // calling into the runtime. | 1768 // calling into the runtime. |
| 1709 __ EnterStubFrame(); | 1769 __ EnterStubFrame(); |
| 1710 __ pushl(EDX); // Preserve arguments descriptor. | 1770 __ pushl(ECX); // Preserve ICData for unoptimized call. |
| 1711 const Immediate& raw_null = | 1771 const Immediate& raw_null = |
| 1712 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1772 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1713 __ pushl(raw_null); // Room for result. | 1773 __ pushl(raw_null); // Room for result. |
| 1714 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1774 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| 1715 __ popl(EAX); // Code object. | 1775 __ popl(EAX); // Code object. |
| 1716 __ popl(EDX); // Restore arguments descriptor. | 1776 __ popl(ECX); // Restore ICData. |
| 1717 __ LeaveFrame(); | 1777 __ LeaveFrame(); |
| 1718 | 1778 |
| 1779 // Load arguments descriptor into EDX. |
| 1780 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1719 // Now call the static function. The breakpoint handler function | 1781 // Now call the static function. The breakpoint handler function |
| 1720 // ensures that the call target is compiled. | 1782 // ensures that the call target is compiled. |
| 1721 // Note that we can't just jump to the CallStatic function stub | 1783 // Note that we can't just jump to the CallStatic function stub |
| 1722 // here since that stub would patch the call site with the | 1784 // here since that stub would patch the call site with the |
| 1723 // static function address. | 1785 // static function address. |
| 1724 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 1786 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 1725 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1787 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1726 __ jmp(ECX); | 1788 __ jmp(ECX); |
| 1727 } | 1789 } |
| 1728 | 1790 |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 __ Bind(&done); | 2179 __ Bind(&done); |
| 2118 __ popl(temp); | 2180 __ popl(temp); |
| 2119 __ popl(right); | 2181 __ popl(right); |
| 2120 __ popl(left); | 2182 __ popl(left); |
| 2121 __ ret(); | 2183 __ ret(); |
| 2122 } | 2184 } |
| 2123 | 2185 |
| 2124 } // namespace dart | 2186 } // namespace dart |
| 2125 | 2187 |
| 2126 #endif // defined TARGET_ARCH_IA32 | 2188 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |