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

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

Issue 17554003: Change static calls in unoptimized code to always call via a stub. Using ICData, the call count of … (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 months 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) 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698