Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 11361225: In optimized code use IC calls for instance calls that have no IC data instead of deoptimizing. The… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/instructions.h" 12 #include "vm/instructions.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/pages.h" 14 #include "vm/pages.h"
15 #include "vm/resolver.h" 15 #include "vm/resolver.h"
16 #include "vm/scavenger.h" 16 #include "vm/scavenger.h"
17 #include "vm/stub_code.h" 17 #include "vm/stub_code.h"
18 18
19 19
20 #define __ assembler-> 20 #define __ assembler->
21 21
22 namespace dart { 22 namespace dart {
23 23
24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
25 DEFINE_FLAG(bool, use_slow_path, false, 25 DEFINE_FLAG(bool, use_slow_path, false,
26 "Set to true for debugging & verifying the slow paths."); 26 "Set to true for debugging & verifying the slow paths.");
27 DECLARE_FLAG(int, optimization_counter_threshold); 27 DECLARE_FLAG(int, optimization_counter_threshold);
28 DECLARE_FLAG(bool, trace_optimized_ic_calls);
28 29
29 // Input parameters: 30 // Input parameters:
30 // ESP : points to return address. 31 // ESP : points to return address.
31 // ESP + 4 : address of last argument in argument array. 32 // ESP + 4 : address of last argument in argument array.
32 // ESP + 4*EDX : address of first argument in argument array. 33 // ESP + 4*EDX : address of first argument in argument array.
33 // ESP + 4*EDX + 4 : address of return value. 34 // ESP + 4*EDX + 4 : address of return value.
34 // ECX : address of the runtime function to call. 35 // ECX : address of the runtime function to call.
35 // EDX : number of arguments to the call. 36 // EDX : number of arguments to the call.
36 // Must preserve callee saved registers EDI and EBX. 37 // Must preserve callee saved registers EDI and EBX.
37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 __ popl(EAX); 1539 __ popl(EAX);
1539 __ popl(EAX); 1540 __ popl(EAX);
1540 __ popl(EAX); // Get result into EAX. 1541 __ popl(EAX); // Get result into EAX.
1541 1542
1542 // Remove the stub frame as we are about to return. 1543 // Remove the stub frame as we are about to return.
1543 __ LeaveFrame(); 1544 __ LeaveFrame();
1544 __ ret(); 1545 __ ret();
1545 } 1546 }
1546 1547
1547 1548
1548 // Loads function into 'temp_reg', preserves 'ic_reg'. 1549 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1550 Register argdesc_reg = EDX;
1551 Register ic_reg = ECX;
1552 Register func_reg = EDI;
1553 if (FLAG_trace_optimized_ic_calls) {
1554 AssemblerMacros::EnterStubFrame(assembler);
1555 __ pushl(func_reg); // Preserve
1556 __ pushl(argdesc_reg); // Preserve.
1557 __ pushl(ic_reg); // Preserve.
1558 __ pushl(ic_reg); // Argument.
1559 __ pushl(func_reg); // Argument.
1560 __ CallRuntime(kTraceICCallRuntimeEntry);
1561 __ popl(EAX); // Discard argument;
1562 __ popl(EAX); // Discard argument;
1563 __ popl(ic_reg); // Restore.
1564 __ popl(argdesc_reg); // Restore.
1565 __ popl(func_reg); // Restore.
1566 __ LeaveFrame();
1567 }
1568 Label is_hot;
1569 if (FlowGraphCompiler::CanOptimize()) {
1570 ASSERT(FLAG_optimization_counter_threshold > 1);
1571 __ cmpl(FieldAddress(func_reg, Function::usage_counter_offset()),
1572 Immediate(FLAG_optimization_counter_threshold));
1573 __ j(GREATER_EQUAL, &is_hot, Assembler::kNearJump);
1574 // As long as VM has no OSR do not optimize in the middle of the function
1575 // but only at exit so that we have collected all type feedback before
1576 // optimizing.
1577 }
1578 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1579 __ Bind(&is_hot);
1580 }
1581
1582
1583
1584 // Loads function into 'temp_reg'.
1549 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1585 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1550 Register ic_reg,
1551 Register temp_reg) { 1586 Register temp_reg) {
1552 __ movl(temp_reg, FieldAddress(ic_reg, ICData::function_offset())); 1587 Register ic_reg = ECX;
1588 Register func_reg = temp_reg;
1589 ASSERT(ic_reg != func_reg);
1590 __ movl(func_reg, FieldAddress(ic_reg, ICData::function_offset()));
1553 Label is_hot; 1591 Label is_hot;
1554 if (FlowGraphCompiler::CanOptimize()) { 1592 if (FlowGraphCompiler::CanOptimize()) {
1555 ASSERT(FLAG_optimization_counter_threshold > 1); 1593 ASSERT(FLAG_optimization_counter_threshold > 1);
1556 // The usage_counter is always less than FLAG_optimization_counter_threshold 1594 // The usage_counter is always less than FLAG_optimization_counter_threshold
1557 // except when the function gets optimized. 1595 // except when the function gets optimized.
1558 __ cmpl(FieldAddress(temp_reg, Function::usage_counter_offset()), 1596 __ cmpl(FieldAddress(func_reg, Function::usage_counter_offset()),
1559 Immediate(FLAG_optimization_counter_threshold)); 1597 Immediate(FLAG_optimization_counter_threshold));
1560 __ j(EQUAL, &is_hot, Assembler::kNearJump); 1598 __ j(EQUAL, &is_hot, Assembler::kNearJump);
1561 // As long as VM has no OSR do not optimize in the middle of the function 1599 // As long as VM has no OSR do not optimize in the middle of the function
1562 // but only at exit so that we have collected all type feedback before 1600 // but only at exit so that we have collected all type feedback before
1563 // optimizing. 1601 // optimizing.
1564 } 1602 }
1565 __ incl(FieldAddress(temp_reg, Function::usage_counter_offset())); 1603 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1566 __ Bind(&is_hot); 1604 __ Bind(&is_hot);
1567 } 1605 }
1568 1606
1569 1607
1570 // Generate inline cache check for 'num_args'. 1608 // Generate inline cache check for 'num_args'.
1571 // ECX: Inline cache data object. 1609 // ECX: Inline cache data object.
1572 // EDX: Arguments descriptor array. 1610 // EDX: Arguments descriptor array.
1573 // TOS(0): return address 1611 // TOS(0): return address
1574 // Control flow: 1612 // Control flow:
1575 // - If receiver is null -> jump to IC miss. 1613 // - If receiver is null -> jump to IC miss.
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 __ popl(EAX); 1715 __ popl(EAX);
1678 } 1716 }
1679 __ popl(EAX); // Pop returned code object into EAX (null if not found). 1717 __ popl(EAX); // Pop returned code object into EAX (null if not found).
1680 __ popl(ECX); // Restore IC data array. 1718 __ popl(ECX); // Restore IC data array.
1681 __ popl(EDX); // Restore arguments array. 1719 __ popl(EDX); // Restore arguments array.
1682 __ LeaveFrame(); 1720 __ LeaveFrame();
1683 Label call_target_function; 1721 Label call_target_function;
1684 __ cmpl(EAX, raw_null); 1722 __ cmpl(EAX, raw_null);
1685 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); 1723 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump);
1686 // NoSuchMethod or closure. 1724 // NoSuchMethod or closure.
1725 // Mark IC call that it may be a closure call that does not collect
1726 // type feedback.
1727 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1));
1687 __ jmp(&StubCode::InstanceFunctionLookupLabel()); 1728 __ jmp(&StubCode::InstanceFunctionLookupLabel());
1688 1729
1689 __ Bind(&found); 1730 __ Bind(&found);
1690 // EBX: Pointer to an IC data check group (classes + target) 1731 // EBX: Pointer to an IC data check group (classes + target)
1691 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. 1732 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function.
1692 1733
1693 __ Bind(&call_target_function); 1734 __ Bind(&call_target_function);
1694 // EAX: Target function. 1735 // EAX: Target function.
1695 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); 1736 __ movl(EAX, FieldAddress(EAX, Function::code_offset()));
1696 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); 1737 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
(...skipping 21 matching lines...) Expand all
1718 // ECX: Inline cache data object. 1759 // ECX: Inline cache data object.
1719 // EDX: Arguments array. 1760 // EDX: Arguments array.
1720 // TOS(0): Return address. 1761 // TOS(0): Return address.
1721 // Inline cache data object structure: 1762 // Inline cache data object structure:
1722 // 0: function-name 1763 // 0: function-name
1723 // 1: N, number of arguments checked. 1764 // 1: N, number of arguments checked.
1724 // 2 .. (length - 1): group of checks, each check containing: 1765 // 2 .. (length - 1): group of checks, each check containing:
1725 // - N classes. 1766 // - N classes.
1726 // - 1 target function. 1767 // - 1 target function.
1727 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1768 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1728 GenerateUsageCounterIncrement(assembler, ECX, EBX); 1769 GenerateUsageCounterIncrement(assembler, EBX);
1729 return GenerateNArgsCheckInlineCacheStub(assembler, 1); 1770 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1730 } 1771 }
1731 1772
1732 1773
1733 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1774 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1734 GenerateUsageCounterIncrement(assembler, ECX, EBX); 1775 GenerateUsageCounterIncrement(assembler, EBX);
1735 return GenerateNArgsCheckInlineCacheStub(assembler, 2); 1776 GenerateNArgsCheckInlineCacheStub(assembler, 2);
1736 } 1777 }
1737 1778
1738 1779
1739 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { 1780 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
1740 GenerateUsageCounterIncrement(assembler, ECX, EBX); 1781 GenerateUsageCounterIncrement(assembler, EBX);
1741 return GenerateNArgsCheckInlineCacheStub(assembler, 3); 1782 GenerateNArgsCheckInlineCacheStub(assembler, 3);
1783 }
1784
1785
1786
1787 // Use inline cache data array to invoke the target or continue in inline
1788 // cache miss handler. Stub for 1-argument check (receiver class).
1789 // EDI: function which counter needs to be incremented.
1790 // ECX: Inline cache data object.
1791 // EDX: Arguments array.
1792 // TOS(0): Return address.
1793 // Inline cache data object structure:
1794 // 0: function-name
1795 // 1: N, number of arguments checked.
1796 // 2 .. (length - 1): group of checks, each check containing:
1797 // - N classes.
1798 // - 1 target function.
1799 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1800 Assembler* assembler) {
1801 GenerateOptimizedUsageCounterIncrement(assembler);
1802 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1803 }
1804
1805
1806 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1807 Assembler* assembler) {
1808 GenerateOptimizedUsageCounterIncrement(assembler);
1809 GenerateNArgsCheckInlineCacheStub(assembler, 2);
1810 }
1811
1812
1813 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
1814 Assembler* assembler) {
1815 GenerateOptimizedUsageCounterIncrement(assembler);
1816 GenerateNArgsCheckInlineCacheStub(assembler, 3);
1817 }
1818
1819
1820 // Do not count as no type feedback is collected.
1821 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
1822 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1742 } 1823 }
1743 1824
1744 1825
1745 // Megamorphic call is currently implemented as IC call but through a stub 1826 // Megamorphic call is currently implemented as IC call but through a stub
1746 // that does not check/count function invocations. 1827 // that does not check/count function invocations.
1747 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { 1828 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
1748 return GenerateNArgsCheckInlineCacheStub(assembler, 1); 1829 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1749 } 1830 }
1750 1831
1751 1832
1752 // ECX: Function object. 1833 // ECX: Function object.
1753 // EDX: Arguments array. 1834 // EDX: Arguments array.
1754 // TOS(0): return address (Dart code). 1835 // TOS(0): return address (Dart code).
1755 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1836 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1756 // Create a stub frame as we are pushing some objects on the stack before 1837 // Create a stub frame as we are pushing some objects on the stack before
1757 // calling into the runtime. 1838 // calling into the runtime.
1758 AssemblerMacros::EnterStubFrame(assembler); 1839 AssemblerMacros::EnterStubFrame(assembler);
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
2080 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); 2161 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry);
2081 __ popl(EDX); 2162 __ popl(EDX);
2082 __ popl(EAX); 2163 __ popl(EAX);
2083 __ LeaveFrame(); 2164 __ LeaveFrame();
2084 __ ret(); 2165 __ ret();
2085 } 2166 }
2086 2167
2087 } // namespace dart 2168 } // namespace dart
2088 2169
2089 #endif // defined TARGET_ARCH_IA32 2170 #endif // defined TARGET_ARCH_IA32
OLDNEW
« runtime/vm/object.h ('K') | « runtime/vm/stub_code.h ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698