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

Side by Side Diff: src/x64/stub-cache-x64.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/x64/code-stubs-x64.cc ('k') | test/mjsunit/array-push.js » ('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 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 index.translate(holder), Representation::Tagged()); 1586 index.translate(holder), Representation::Tagged());
1587 GenerateJumpFunction(object, rdi, &miss); 1587 GenerateJumpFunction(object, rdi, &miss);
1588 1588
1589 HandlerFrontendFooter(&miss); 1589 HandlerFrontendFooter(&miss);
1590 1590
1591 // Return the generated code. 1591 // Return the generated code.
1592 return GetCode(Code::FAST, name); 1592 return GetCode(Code::FAST, name);
1593 } 1593 }
1594 1594
1595 1595
1596 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1597 Handle<Object> object,
1598 Handle<JSObject> holder,
1599 Handle<Cell> cell,
1600 Handle<JSFunction> function,
1601 Handle<String> name,
1602 Code::StubType type) {
1603 // If object is not an array or is observed or sealed, bail out to regular
1604 // call.
1605 if (!object->IsJSArray() ||
1606 !cell.is_null() ||
1607 Handle<JSArray>::cast(object)->map()->is_observed() ||
1608 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1609 return Handle<Code>::null();
1610 }
1611
1612 Label miss;
1613
1614 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1615
1616 const int argc = arguments().immediate();
1617 StackArgumentsAccessor args(rsp, argc);
1618 if (argc == 0) {
1619 // Noop, return the length.
1620 __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1621 __ ret((argc + 1) * kPointerSize);
1622 } else {
1623 Label call_builtin;
1624
1625 if (argc == 1) { // Otherwise fall through to call builtin.
1626 Label attempt_to_grow_elements, with_write_barrier, check_double;
1627
1628 // Get the elements array of the object.
1629 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1630
1631 // Check that the elements are in fast mode and writable.
1632 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
1633 factory()->fixed_array_map());
1634 __ j(not_equal, &check_double);
1635
1636 // Get the array's length into rax and calculate new length.
1637 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1638 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1639 __ addl(rax, Immediate(argc));
1640
1641 // Get the elements' length into rcx.
1642 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1643
1644 // Check if we could survive without allocation.
1645 __ cmpl(rax, rcx);
1646 __ j(greater, &attempt_to_grow_elements);
1647
1648 // Check if value is a smi.
1649 __ movp(rcx, args.GetArgumentOperand(1));
1650 __ JumpIfNotSmi(rcx, &with_write_barrier);
1651
1652 // Save new length.
1653 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1654
1655 // Store the value.
1656 __ movp(FieldOperand(rdi,
1657 rax,
1658 times_pointer_size,
1659 FixedArray::kHeaderSize - argc * kPointerSize),
1660 rcx);
1661
1662 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1663 __ ret((argc + 1) * kPointerSize);
1664
1665 __ bind(&check_double);
1666
1667 // Check that the elements are in double mode.
1668 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
1669 factory()->fixed_double_array_map());
1670 __ j(not_equal, &call_builtin);
1671
1672 // Get the array's length into rax and calculate new length.
1673 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1674 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1675 __ addl(rax, Immediate(argc));
1676
1677 // Get the elements' length into rcx.
1678 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1679
1680 // Check if we could survive without allocation.
1681 __ cmpl(rax, rcx);
1682 __ j(greater, &call_builtin);
1683
1684 __ movp(rcx, args.GetArgumentOperand(1));
1685 __ StoreNumberToDoubleElements(
1686 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
1687
1688 // Save new length.
1689 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1690 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1691 __ ret((argc + 1) * kPointerSize);
1692
1693 __ bind(&with_write_barrier);
1694
1695 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
1696
1697 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1698 Label fast_object, not_fast_object;
1699 __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
1700 __ jmp(&fast_object);
1701 // In case of fast smi-only, convert to fast object, otherwise bail out.
1702 __ bind(&not_fast_object);
1703 __ CheckFastSmiElements(rbx, &call_builtin);
1704 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
1705 factory()->heap_number_map());
1706 __ j(equal, &call_builtin);
1707 // rdx: receiver
1708 // rbx: map
1709
1710 Label try_holey_map;
1711 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1712 FAST_ELEMENTS,
1713 rbx,
1714 rdi,
1715 &try_holey_map);
1716
1717 ElementsTransitionGenerator::
1718 GenerateMapChangeElementsTransition(masm(),
1719 DONT_TRACK_ALLOCATION_SITE,
1720 NULL);
1721 // Restore edi.
1722 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1723 __ jmp(&fast_object);
1724
1725 __ bind(&try_holey_map);
1726 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1727 FAST_HOLEY_ELEMENTS,
1728 rbx,
1729 rdi,
1730 &call_builtin);
1731 ElementsTransitionGenerator::
1732 GenerateMapChangeElementsTransition(masm(),
1733 DONT_TRACK_ALLOCATION_SITE,
1734 NULL);
1735 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1736 __ bind(&fast_object);
1737 } else {
1738 __ CheckFastObjectElements(rbx, &call_builtin);
1739 }
1740
1741 // Save new length.
1742 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1743
1744 // Store the value.
1745 __ lea(rdx, FieldOperand(rdi,
1746 rax, times_pointer_size,
1747 FixedArray::kHeaderSize - argc * kPointerSize));
1748 __ movp(Operand(rdx, 0), rcx);
1749
1750 __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1751 OMIT_SMI_CHECK);
1752
1753 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1754 __ ret((argc + 1) * kPointerSize);
1755
1756 __ bind(&attempt_to_grow_elements);
1757 if (!FLAG_inline_new) {
1758 __ jmp(&call_builtin);
1759 }
1760
1761 __ movp(rbx, args.GetArgumentOperand(1));
1762 // Growing elements that are SMI-only requires special handling in case
1763 // the new element is non-Smi. For now, delegate to the builtin.
1764 Label no_fast_elements_check;
1765 __ JumpIfSmi(rbx, &no_fast_elements_check);
1766 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1767 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
1768 __ bind(&no_fast_elements_check);
1769
1770 ExternalReference new_space_allocation_top =
1771 ExternalReference::new_space_allocation_top_address(isolate());
1772 ExternalReference new_space_allocation_limit =
1773 ExternalReference::new_space_allocation_limit_address(isolate());
1774
1775 const int kAllocationDelta = 4;
1776 // Load top.
1777 __ Load(rcx, new_space_allocation_top);
1778
1779 // Check if it's the end of elements.
1780 __ lea(rdx, FieldOperand(rdi,
1781 rax, times_pointer_size,
1782 FixedArray::kHeaderSize - argc * kPointerSize));
1783 __ cmpq(rdx, rcx);
1784 __ j(not_equal, &call_builtin);
1785 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
1786 Operand limit_operand =
1787 masm()->ExternalOperand(new_space_allocation_limit);
1788 __ cmpq(rcx, limit_operand);
1789 __ j(above, &call_builtin);
1790
1791 // We fit and could grow elements.
1792 __ Store(new_space_allocation_top, rcx);
1793
1794 // Push the argument...
1795 __ movp(Operand(rdx, 0), rbx);
1796 // ... and fill the rest with holes.
1797 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
1798 for (int i = 1; i < kAllocationDelta; i++) {
1799 __ movp(Operand(rdx, i * kPointerSize), kScratchRegister);
1800 }
1801
1802 // We know the elements array is in new space so we don't need the
1803 // remembered set, but we just pushed a value onto it so we may have to
1804 // tell the incremental marker to rescan the object that we just grew. We
1805 // don't need to worry about the holes because they are in old space and
1806 // already marked black.
1807 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1808
1809 // Restore receiver to rdx as finish sequence assumes it's here.
1810 __ movp(rdx, args.GetReceiverOperand());
1811
1812 // Increment element's and array's sizes.
1813 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
1814 Smi::FromInt(kAllocationDelta));
1815
1816 // Make new length a smi before returning it.
1817 __ Integer32ToSmi(rax, rax);
1818 __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1819
1820 __ ret((argc + 1) * kPointerSize);
1821 }
1822
1823 __ bind(&call_builtin);
1824 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
1825 isolate()),
1826 argc + 1,
1827 1);
1828 }
1829
1830 HandlerFrontendFooter(&miss);
1831
1832 // Return the generated code.
1833 return GetCode(type, name);
1834 }
1835
1836
1837 Handle<Code> CallStubCompiler::CompileFastApiCall( 1596 Handle<Code> CallStubCompiler::CompileFastApiCall(
1838 const CallOptimization& optimization, 1597 const CallOptimization& optimization,
1839 Handle<Object> object, 1598 Handle<Object> object,
1840 Handle<JSObject> holder, 1599 Handle<JSObject> holder,
1841 Handle<Cell> cell, 1600 Handle<Cell> cell,
1842 Handle<JSFunction> function, 1601 Handle<JSFunction> function,
1843 Handle<String> name) { 1602 Handle<String> name) {
1844 ASSERT(optimization.is_simple_api_call()); 1603 ASSERT(optimization.is_simple_api_call());
1845 // Bail out if object is a global object as we don't want to 1604 // Bail out if object is a global object as we don't want to
1846 // repatch it to global receiver. 1605 // repatch it to global receiver.
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
2419 // ----------------------------------- 2178 // -----------------------------------
2420 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2179 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2421 } 2180 }
2422 2181
2423 2182
2424 #undef __ 2183 #undef __
2425 2184
2426 } } // namespace v8::internal 2185 } } // namespace v8::internal
2427 2186
2428 #endif // V8_TARGET_ARCH_X64 2187 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | test/mjsunit/array-push.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698