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

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

Issue 10910224: Using type feedback, eliminate store barriers for indexed stores. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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) 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
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
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, &not_smi, Assembler::kNearJump); 1699 __ j(NOT_ZERO, &not_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(&not_smi); 1703 __ Bind(&not_smi);
1708 __ LoadClassId(EAX, EAX); 1704 __ LoadClassId(EAX, EAX);
(...skipping 15 matching lines...) Expand all
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698