Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1548 // ECX: Inline cache data object. | 1548 // ECX: Inline cache data object. |
| 1549 // EDX: Arguments descriptor array. | 1549 // EDX: Arguments descriptor array. |
| 1550 // TOS(0): return address | 1550 // TOS(0): return address |
| 1551 // Control flow: | 1551 // Control flow: |
| 1552 // - If receiver is null -> jump to IC miss. | 1552 // - If receiver is null -> jump to IC miss. |
| 1553 // - If receiver is Smi -> load Smi class. | 1553 // - If receiver is Smi -> load Smi class. |
| 1554 // - If receiver is not-Smi -> load receiver's class. | 1554 // - If receiver is not-Smi -> load receiver's class. |
| 1555 // - Check if 'num_args' (including receiver) match any IC data group. | 1555 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1556 // - Match found -> jump to target. | 1556 // - Match found -> jump to target. |
| 1557 // - Match not found -> jump to IC miss. | 1557 // - Match not found -> jump to IC miss. |
| 1558 // TODO(srdjan): Change IC data to keep class ids as integers not as Smi-s. | |
| 1559 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1558 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1560 intptr_t num_args) { | 1559 intptr_t num_args) { |
| 1561 const Immediate raw_null = | 1560 const Immediate raw_null = |
| 1562 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1561 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1563 | 1562 |
| 1564 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); | 1563 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); |
| 1565 Label is_hot; | 1564 Label is_hot; |
| 1566 if (FlowGraphCompiler::CanOptimize()) { | 1565 if (FlowGraphCompiler::CanOptimize()) { |
| 1567 ASSERT(FLAG_optimization_counter_threshold > 1); | 1566 ASSERT(FLAG_optimization_counter_threshold > 1); |
| 1568 // The usage_counter is always less than FLAG_optimization_counter_threshold | 1567 // The usage_counter is always less than FLAG_optimization_counter_threshold |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1612 if (num_args == 1) { | 1611 if (num_args == 1) { |
| 1613 __ call(&get_class_id_as_smi); | 1612 __ call(&get_class_id_as_smi); |
| 1614 // EAX: receiver's class id Smi. | 1613 // EAX: receiver's class id Smi. |
| 1615 __ Bind(&loop); | 1614 __ Bind(&loop); |
| 1616 __ movl(EDI, Address(EBX, 0)); // Get class id (Smi) to check. | 1615 __ movl(EDI, Address(EBX, 0)); // Get class id (Smi) to check. |
| 1617 __ cmpl(EAX, EDI); // Class id match? | 1616 __ cmpl(EAX, EDI); // Class id match? |
| 1618 __ j(EQUAL, &found, Assembler::kNearJump); | 1617 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1619 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1618 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1620 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1619 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1621 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1620 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1622 } else if (num_args == 2) { | 1621 } else { |
| 1623 // EDI: class to check. | |
| 1624 Label no_match; | 1622 Label no_match; |
| 1625 __ Bind(&loop); | 1623 __ Bind(&loop); |
| 1626 // Get class id from IC data to check. | 1624 for (int i = 0; i < num_args; i++) { |
| 1627 // Get receiver using argument descriptor in EDX. | 1625 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1628 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1626 __ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize)); |
| 1629 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. | 1627 __ call(&get_class_id_as_smi); |
| 1630 __ call(&get_class_id_as_smi); | 1628 __ movl(EDI, Address(EBX, i * kWordSize)); |
| 1631 __ movl(EDI, Address(EBX, 0)); | 1629 __ cmpl(EAX, EDI); // Class id match? |
| 1632 __ cmpl(EAX, EDI); // Class id match? | 1630 if (i < (num_args - 1)) { |
| 1633 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1631 __ j(NOT_EQUAL, &no_match); |
| 1634 // Check second class/argument. | 1632 } else { |
| 1635 // Get class id from IC data to check. | 1633 // Last check, all checks before matched. |
| 1636 // Get next argument. | 1634 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1637 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1635 } |
| 1638 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); | 1636 } |
| 1639 // EAX (argument count) is Smi. | |
| 1640 __ call(&get_class_id_as_smi); | |
| 1641 __ movl(EDI, Address(EBX, kWordSize)); | |
| 1642 __ cmpl(EAX, EDI); // Class id match? | |
| 1643 __ j(EQUAL, &found, Assembler::kNearJump); | |
| 1644 __ Bind(&no_match); | 1637 __ Bind(&no_match); |
| 1645 // Each test entry has (1 + num_args) array elements. | 1638 // Each test entry has (1 + num_args) array elements. |
| 1646 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1639 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1647 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1640 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1648 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1641 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1649 } | 1642 } |
| 1650 | 1643 |
| 1651 __ Bind(&ic_miss); | 1644 __ Bind(&ic_miss); |
| 1652 // Compute address of arguments (first read number of arguments from argument | 1645 // Compute address of arguments (first read number of arguments from argument |
| 1653 // descriptor array and then compute address on the stack). | 1646 // descriptor array and then compute address on the stack). |
| 1654 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1647 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1655 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1648 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1656 // Create a stub frame as we are pushing some objects on the stack before | 1649 // Create a stub frame as we are pushing some objects on the stack before |
| 1657 // calling into the runtime. | 1650 // calling into the runtime. |
| 1658 AssemblerMacros::EnterStubFrame(assembler); | 1651 AssemblerMacros::EnterStubFrame(assembler); |
| 1659 __ pushl(EDX); // Preserve arguments array. | 1652 __ pushl(EDX); // Preserve arguments array. |
| 1660 __ pushl(ECX); // Preserve IC data array | 1653 __ pushl(ECX); // Preserve IC data array |
| 1661 __ pushl(raw_null); // Setup space on stack for result (target code object). | 1654 __ pushl(raw_null); // Setup space on stack for result (target code object). |
| 1662 // Push call arguments. | 1655 // Push call arguments. |
| 1663 for (intptr_t i = 0; i < num_args; i++) { | 1656 for (intptr_t i = 0; i < num_args; i++) { |
| 1664 __ movl(EDX, Address(EAX, -kWordSize * i)); | 1657 __ movl(EDX, Address(EAX, -kWordSize * i)); |
| 1665 __ pushl(EDX); | 1658 __ pushl(EDX); |
| 1666 } | 1659 } |
| 1667 if (num_args == 1) { | 1660 if (num_args == 1) { |
| 1668 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1661 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1669 } else if (num_args == 2) { | 1662 } else if (num_args == 2) { |
| 1670 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1663 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1664 } else if (num_args == 3) { | |
| 1665 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); | |
| 1671 } else { | 1666 } else { |
| 1672 UNIMPLEMENTED(); | 1667 UNIMPLEMENTED(); |
| 1673 } | 1668 } |
| 1674 // Remove call arguments pushed earlier. | 1669 // Remove call arguments pushed earlier. |
| 1675 for (intptr_t i = 0; i < num_args; i++) { | 1670 for (intptr_t i = 0; i < num_args; i++) { |
| 1676 __ popl(EAX); | 1671 __ popl(EAX); |
| 1677 } | 1672 } |
| 1678 __ popl(EAX); // Pop returned code object into EAX (null if not found). | 1673 __ popl(EAX); // Pop returned code object into EAX (null if not found). |
| 1679 __ popl(ECX); // Restore IC data array. | 1674 __ popl(ECX); // Restore IC data array. |
| 1680 __ popl(EDX); // Restore arguments array. | 1675 __ popl(EDX); // Restore arguments array. |
| 1681 __ LeaveFrame(); | 1676 __ LeaveFrame(); |
| 1682 Label call_target_function; | 1677 Label call_target_function; |
| 1683 __ cmpl(EAX, raw_null); | 1678 __ cmpl(EAX, raw_null); |
| 1684 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1679 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
| 1685 // NoSuchMethod or closure. | 1680 // NoSuchMethod or closure. |
| 1686 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 1681 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 1687 | 1682 |
| 1688 __ Bind(&found); | 1683 __ Bind(&found); |
| 1689 // EBX: Pointer to an IC data check group (classes + target) | 1684 // EBX: Pointer to an IC data check group (classes + target) |
| 1690 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. | 1685 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. |
| 1691 | 1686 |
| 1692 __ Bind(&call_target_function); | 1687 __ Bind(&call_target_function); |
| 1693 // EAX: Target function. | 1688 // EAX: Target function. |
| 1694 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 1689 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 1695 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1690 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1696 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1691 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1697 __ jmp(EAX); | 1692 __ jmp(EAX); |
| 1698 | 1693 |
| 1694 // Instance in EAX, return its class-id in EAX as Smi. | |
| 1699 __ Bind(&get_class_id_as_smi); | 1695 __ Bind(&get_class_id_as_smi); |
| 1700 Label not_smi; | 1696 Label not_smi; |
| 1701 // Test if Smi -> load Smi class for comparison. | 1697 // Test if Smi -> load Smi class for comparison. |
| 1702 __ testl(EAX, Immediate(kSmiTagMask)); | 1698 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1703 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1699 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1704 __ movl(EAX, Immediate(Smi::RawValue(kSmiCid))); | 1700 __ movl(EAX, Immediate(Smi::RawValue(kSmiCid))); |
| 1705 __ ret(); | 1701 __ ret(); |
| 1706 | 1702 |
| 1707 __ Bind(¬_smi); | 1703 __ Bind(¬_smi); |
| 1708 __ LoadClassId(EAX, EAX); | 1704 __ LoadClassId(EAX, EAX); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1724 // - 1 target function. | 1720 // - 1 target function. |
| 1725 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1721 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1726 return GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1722 return GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1727 } | 1723 } |
| 1728 | 1724 |
| 1729 | 1725 |
| 1730 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1726 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1731 return GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1727 return GenerateNArgsCheckInlineCacheStub(assembler, 2); |
| 1732 } | 1728 } |
| 1733 | 1729 |
| 1730 | |
| 1731 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | |
| 1732 return GenerateNArgsCheckInlineCacheStub(assembler, 3); | |
| 1733 } | |
| 1734 | |
| 1735 | |
| 1734 // ECX: Function object. | 1736 // ECX: Function object. |
| 1735 // EDX: Arguments array. | 1737 // EDX: Arguments array. |
| 1736 // TOS(0): return address (Dart code). | 1738 // TOS(0): return address (Dart code). |
| 1737 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1739 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1738 // Create a stub frame as we are pushing some objects on the stack before | 1740 // Create a stub frame as we are pushing some objects on the stack before |
| 1739 // calling into the runtime. | 1741 // calling into the runtime. |
| 1740 AssemblerMacros::EnterStubFrame(assembler); | 1742 AssemblerMacros::EnterStubFrame(assembler); |
| 1741 __ pushl(EDX); | 1743 __ pushl(EDX); |
| 1742 __ pushl(ECX); | 1744 __ pushl(ECX); |
| 1743 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1745 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1788 __ LeaveFrame(); | 1790 __ LeaveFrame(); |
| 1789 | 1791 |
| 1790 // Find out which dispatch stub to call. | 1792 // Find out which dispatch stub to call. |
| 1791 Label ic_cache_one_arg; | 1793 Label ic_cache_one_arg; |
| 1792 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1794 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1793 __ cmpl(EBX, Immediate(1)); | 1795 __ cmpl(EBX, Immediate(1)); |
| 1794 __ j(EQUAL, &ic_cache_one_arg, Assembler::kNearJump); | 1796 __ j(EQUAL, &ic_cache_one_arg, Assembler::kNearJump); |
| 1795 __ jmp(&StubCode::TwoArgsCheckInlineCacheLabel()); | 1797 __ jmp(&StubCode::TwoArgsCheckInlineCacheLabel()); |
| 1796 __ Bind(&ic_cache_one_arg); | 1798 __ Bind(&ic_cache_one_arg); |
| 1797 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1799 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1800 | |
| 1801 Label test_two, test_three, test_four; | |
|
Vyacheslav Egorov (Google)
2012/09/12 15:38:09
I think you need to remove the code above (this co
srdjan
2012/09/12 15:45:25
Done.
| |
| 1802 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | |
| 1803 __ cmpl(EBX, Immediate(1)); | |
| 1804 __ j(NOT_EQUAL, &test_two, Assembler::kNearJump); | |
| 1805 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | |
| 1806 __ Bind(&test_two); | |
| 1807 __ cmpl(EBX, Immediate(2)); | |
| 1808 __ j(NOT_EQUAL, &test_three, Assembler::kNearJump); | |
| 1809 __ jmp(&StubCode::TwoArgsCheckInlineCacheLabel()); | |
| 1810 __ Bind(&test_three); | |
| 1811 __ cmpl(EBX, Immediate(3)); | |
| 1812 __ j(NOT_EQUAL, &test_four, Assembler::kNearJump); | |
| 1813 __ jmp(&StubCode::ThreeArgsCheckInlineCacheLabel()); | |
| 1814 __ Bind(&test_four); | |
| 1815 __ Stop("Unsupported number of arguments tested."); | |
| 1798 } | 1816 } |
| 1799 | 1817 |
| 1800 | 1818 |
| 1801 // Used to check class and type arguments. Arguments passed on stack: | 1819 // Used to check class and type arguments. Arguments passed on stack: |
| 1802 // TOS + 0: return address. | 1820 // TOS + 0: return address. |
| 1803 // TOS + 1: instantiator type arguments (can be NULL). | 1821 // TOS + 1: instantiator type arguments (can be NULL). |
| 1804 // TOS + 2: instance. | 1822 // TOS + 2: instance. |
| 1805 // TOS + 3: SubtypeTestCache. | 1823 // TOS + 3: SubtypeTestCache. |
| 1806 // Result in ECX: null -> not found, otherwise result (true or false). | 1824 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1807 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1825 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1949 __ movl(EAX, Address(ESP, 4 * kWordSize)); // Load error object. | 1967 __ movl(EAX, Address(ESP, 4 * kWordSize)); // Load error object. |
| 1950 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer. | 1968 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer. |
| 1951 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX. | 1969 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX. |
| 1952 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer. | 1970 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer. |
| 1953 __ jmp(EBX); // Jump to the exception handler code. | 1971 __ jmp(EBX); // Jump to the exception handler code. |
| 1954 } | 1972 } |
| 1955 | 1973 |
| 1956 } // namespace dart | 1974 } // namespace dart |
| 1957 | 1975 |
| 1958 #endif // defined TARGET_ARCH_IA32 | 1976 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |