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

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 143213003: Turn ArrayPush into a stub specialized on the elements kind and argc. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Properly bind label Created 6 years, 11 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
« no previous file with comments | « src/ia32/code-stubs-ia32.cc ('k') | src/stub-cache.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 index.translate(holder), Representation::Tagged()); 1659 index.translate(holder), Representation::Tagged());
1660 GenerateJumpFunction(object, edi, &miss); 1660 GenerateJumpFunction(object, edi, &miss);
1661 1661
1662 HandlerFrontendFooter(&miss); 1662 HandlerFrontendFooter(&miss);
1663 1663
1664 // Return the generated code. 1664 // Return the generated code.
1665 return GetCode(Code::FAST, name); 1665 return GetCode(Code::FAST, name);
1666 } 1666 }
1667 1667
1668 1668
1669 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1670 Handle<Object> object,
1671 Handle<JSObject> holder,
1672 Handle<Cell> cell,
1673 Handle<JSFunction> function,
1674 Handle<String> name,
1675 Code::StubType type) {
1676 // If object is not an array or is observed or sealed, bail out to regular
1677 // call.
1678 if (!object->IsJSArray() ||
1679 !cell.is_null() ||
1680 Handle<JSArray>::cast(object)->map()->is_observed() ||
1681 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1682 return Handle<Code>::null();
1683 }
1684
1685 Label miss;
1686
1687 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1688
1689 const int argc = arguments().immediate();
1690 if (argc == 0) {
1691 // Noop, return the length.
1692 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1693 __ ret((argc + 1) * kPointerSize);
1694 } else {
1695 Label call_builtin;
1696
1697 if (argc == 1) { // Otherwise fall through to call builtin.
1698 Label attempt_to_grow_elements, with_write_barrier, check_double;
1699
1700 // Get the elements array of the object.
1701 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1702
1703 // Check that the elements are in fast mode and writable.
1704 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
1705 Immediate(factory()->fixed_array_map()));
1706 __ j(not_equal, &check_double);
1707
1708 // Get the array's length into eax and calculate new length.
1709 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1710 STATIC_ASSERT(kSmiTagSize == 1);
1711 STATIC_ASSERT(kSmiTag == 0);
1712 __ add(eax, Immediate(Smi::FromInt(argc)));
1713
1714 // Get the elements' length into ecx.
1715 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
1716
1717 // Check if we could survive without allocation.
1718 __ cmp(eax, ecx);
1719 __ j(greater, &attempt_to_grow_elements);
1720
1721 // Check if value is a smi.
1722 __ mov(ecx, Operand(esp, argc * kPointerSize));
1723 __ JumpIfNotSmi(ecx, &with_write_barrier);
1724
1725 // Save new length.
1726 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1727
1728 // Store the value.
1729 __ mov(FieldOperand(edi,
1730 eax,
1731 times_half_pointer_size,
1732 FixedArray::kHeaderSize - argc * kPointerSize),
1733 ecx);
1734
1735 __ ret((argc + 1) * kPointerSize);
1736
1737 __ bind(&check_double);
1738
1739
1740 // Check that the elements are in double mode.
1741 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
1742 Immediate(factory()->fixed_double_array_map()));
1743 __ j(not_equal, &call_builtin);
1744
1745 // Get the array's length into eax and calculate new length.
1746 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1747 STATIC_ASSERT(kSmiTagSize == 1);
1748 STATIC_ASSERT(kSmiTag == 0);
1749 __ add(eax, Immediate(Smi::FromInt(argc)));
1750
1751 // Get the elements' length into ecx.
1752 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
1753
1754 // Check if we could survive without allocation.
1755 __ cmp(eax, ecx);
1756 __ j(greater, &call_builtin);
1757
1758 __ mov(ecx, Operand(esp, argc * kPointerSize));
1759 __ StoreNumberToDoubleElements(
1760 ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize);
1761
1762 // Save new length.
1763 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1764 __ ret((argc + 1) * kPointerSize);
1765
1766 __ bind(&with_write_barrier);
1767
1768 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1769
1770 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1771 Label fast_object, not_fast_object;
1772 __ CheckFastObjectElements(ebx, &not_fast_object, Label::kNear);
1773 __ jmp(&fast_object);
1774 // In case of fast smi-only, convert to fast object, otherwise bail out.
1775 __ bind(&not_fast_object);
1776 __ CheckFastSmiElements(ebx, &call_builtin);
1777 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
1778 Immediate(factory()->heap_number_map()));
1779 __ j(equal, &call_builtin);
1780 // edi: elements array
1781 // edx: receiver
1782 // ebx: map
1783 Label try_holey_map;
1784 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1785 FAST_ELEMENTS,
1786 ebx,
1787 edi,
1788 &try_holey_map);
1789
1790 ElementsTransitionGenerator::
1791 GenerateMapChangeElementsTransition(masm(),
1792 DONT_TRACK_ALLOCATION_SITE,
1793 NULL);
1794 // Restore edi.
1795 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1796 __ jmp(&fast_object);
1797
1798 __ bind(&try_holey_map);
1799 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1800 FAST_HOLEY_ELEMENTS,
1801 ebx,
1802 edi,
1803 &call_builtin);
1804 ElementsTransitionGenerator::
1805 GenerateMapChangeElementsTransition(masm(),
1806 DONT_TRACK_ALLOCATION_SITE,
1807 NULL);
1808 // Restore edi.
1809 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1810 __ bind(&fast_object);
1811 } else {
1812 __ CheckFastObjectElements(ebx, &call_builtin);
1813 }
1814
1815 // Save new length.
1816 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1817
1818 // Store the value.
1819 __ lea(edx, FieldOperand(edi,
1820 eax, times_half_pointer_size,
1821 FixedArray::kHeaderSize - argc * kPointerSize));
1822 __ mov(Operand(edx, 0), ecx);
1823
1824 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1825 OMIT_SMI_CHECK);
1826
1827 __ ret((argc + 1) * kPointerSize);
1828
1829 __ bind(&attempt_to_grow_elements);
1830 if (!FLAG_inline_new) {
1831 __ jmp(&call_builtin);
1832 }
1833
1834 __ mov(ebx, Operand(esp, argc * kPointerSize));
1835 // Growing elements that are SMI-only requires special handling in case
1836 // the new element is non-Smi. For now, delegate to the builtin.
1837 Label no_fast_elements_check;
1838 __ JumpIfSmi(ebx, &no_fast_elements_check);
1839 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1840 __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
1841 __ bind(&no_fast_elements_check);
1842
1843 // We could be lucky and the elements array could be at the top of
1844 // new-space. In this case we can just grow it in place by moving the
1845 // allocation pointer up.
1846
1847 ExternalReference new_space_allocation_top =
1848 ExternalReference::new_space_allocation_top_address(isolate());
1849 ExternalReference new_space_allocation_limit =
1850 ExternalReference::new_space_allocation_limit_address(isolate());
1851
1852 const int kAllocationDelta = 4;
1853 // Load top.
1854 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
1855
1856 // Check if it's the end of elements.
1857 __ lea(edx, FieldOperand(edi,
1858 eax, times_half_pointer_size,
1859 FixedArray::kHeaderSize - argc * kPointerSize));
1860 __ cmp(edx, ecx);
1861 __ j(not_equal, &call_builtin);
1862 __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
1863 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
1864 __ j(above, &call_builtin);
1865
1866 // We fit and could grow elements.
1867 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
1868
1869 // Push the argument...
1870 __ mov(Operand(edx, 0), ebx);
1871 // ... and fill the rest with holes.
1872 for (int i = 1; i < kAllocationDelta; i++) {
1873 __ mov(Operand(edx, i * kPointerSize),
1874 Immediate(factory()->the_hole_value()));
1875 }
1876
1877 // We know the elements array is in new space so we don't need the
1878 // remembered set, but we just pushed a value onto it so we may have to
1879 // tell the incremental marker to rescan the object that we just grew. We
1880 // don't need to worry about the holes because they are in old space and
1881 // already marked black.
1882 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1883
1884 // Restore receiver to edx as finish sequence assumes it's here.
1885 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1886
1887 // Increment element's and array's sizes.
1888 __ add(FieldOperand(edi, FixedArray::kLengthOffset),
1889 Immediate(Smi::FromInt(kAllocationDelta)));
1890
1891 // NOTE: This only happen in new-space, where we don't
1892 // care about the black-byte-count on pages. Otherwise we should
1893 // update that too if the object is black.
1894
1895 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1896
1897 __ ret((argc + 1) * kPointerSize);
1898 }
1899
1900 __ bind(&call_builtin);
1901 __ TailCallExternalReference(
1902 ExternalReference(Builtins::c_ArrayPush, isolate()),
1903 argc + 1,
1904 1);
1905 }
1906
1907 HandlerFrontendFooter(&miss);
1908
1909 // Return the generated code.
1910 return GetCode(type, name);
1911 }
1912
1913
1914 Handle<Code> CallStubCompiler::CompileFastApiCall( 1669 Handle<Code> CallStubCompiler::CompileFastApiCall(
1915 const CallOptimization& optimization, 1670 const CallOptimization& optimization,
1916 Handle<Object> object, 1671 Handle<Object> object,
1917 Handle<JSObject> holder, 1672 Handle<JSObject> holder,
1918 Handle<Cell> cell, 1673 Handle<Cell> cell,
1919 Handle<JSFunction> function, 1674 Handle<JSFunction> function,
1920 Handle<String> name) { 1675 Handle<String> name) {
1921 ASSERT(optimization.is_simple_api_call()); 1676 ASSERT(optimization.is_simple_api_call());
1922 // Bail out if object is a global object as we don't want to 1677 // Bail out if object is a global object as we don't want to
1923 // repatch it to global receiver. 1678 // repatch it to global receiver.
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
2491 // ----------------------------------- 2246 // -----------------------------------
2492 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2247 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2493 } 2248 }
2494 2249
2495 2250
2496 #undef __ 2251 #undef __
2497 2252
2498 } } // namespace v8::internal 2253 } } // namespace v8::internal
2499 2254
2500 #endif // V8_TARGET_ARCH_IA32 2255 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.cc ('k') | src/stub-cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698