OLD | NEW |
---|---|
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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 // ----------- S t a t e ------------- | 750 // ----------- S t a t e ------------- |
751 // -- r0: receiver | 751 // -- r0: receiver |
752 // -- r1: function to call | 752 // -- r1: function to call |
753 // ----------------------------------- | 753 // ----------------------------------- |
754 | 754 |
755 // Check that the function really is a function. | 755 // Check that the function really is a function. |
756 __ JumpIfSmi(r1, miss); | 756 __ JumpIfSmi(r1, miss); |
757 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 757 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
758 __ b(ne, miss); | 758 __ b(ne, miss); |
759 | 759 |
760 // Patch the receiver on the stack with the global proxy if | |
761 // necessary. | |
762 if (object->IsGlobalObject()) { | 760 if (object->IsGlobalObject()) { |
Igor Sheludko
2013/11/28 12:54:27
Looks like PatchGlobalProxy(object);
Why don't mak
| |
761 const int argc = arguments.immediate(); | |
762 const int receiver_offset = argc * kPointerSize; | |
763 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 763 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
764 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); | 764 __ str(r3, MemOperand(sp, receiver_offset)); |
765 } | 765 } |
766 | 766 |
767 // Invoke the function. | 767 // Invoke the function. |
768 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 768 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
769 ? CALL_AS_FUNCTION | 769 ? CALL_AS_FUNCTION |
770 : CALL_AS_METHOD; | 770 : CALL_AS_METHOD; |
771 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 771 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
772 } | 772 } |
773 | 773 |
774 | 774 |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1542 | 1542 |
1543 | 1543 |
1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1545 if (kind_ == Code::KEYED_CALL_IC) { | 1545 if (kind_ == Code::KEYED_CALL_IC) { |
1546 __ cmp(r2, Operand(name)); | 1546 __ cmp(r2, Operand(name)); |
1547 __ b(ne, miss); | 1547 __ b(ne, miss); |
1548 } | 1548 } |
1549 } | 1549 } |
1550 | 1550 |
1551 | 1551 |
1552 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | |
1553 Handle<JSObject> holder, | |
1554 Handle<Name> name, | |
1555 Label* miss) { | |
1556 ASSERT(holder->IsGlobalObject()); | |
1557 | |
1558 // Get the number of arguments. | |
1559 const int argc = arguments().immediate(); | |
1560 | |
1561 // Get the receiver from the stack. | |
1562 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | |
1563 | |
1564 // Check that the maps haven't changed. | |
1565 __ JumpIfSmi(r0, miss); | |
1566 CheckPrototypes( | |
1567 IC::CurrentTypeOf(object, isolate()), r0, holder, r3, r1, r4, name, miss); | |
1568 } | |
1569 | |
1570 | |
1571 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1552 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1572 Handle<Cell> cell, | 1553 Handle<Cell> cell, |
1573 Handle<JSFunction> function, | 1554 Handle<JSFunction> function, |
1574 Label* miss) { | 1555 Label* miss) { |
1575 // Get the value from the cell. | 1556 // Get the value from the cell. |
1576 __ mov(r3, Operand(cell)); | 1557 __ mov(r3, Operand(cell)); |
1577 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | 1558 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); |
1578 | 1559 |
1579 // Check that the cell contains the same function. | 1560 // Check that the cell contains the same function. |
1580 if (heap()->InNewSpace(*function)) { | 1561 if (heap()->InNewSpace(*function)) { |
(...skipping 23 matching lines...) Expand all Loading... | |
1604 kind_, | 1585 kind_, |
1605 extra_state_); | 1586 extra_state_); |
1606 __ Jump(code, RelocInfo::CODE_TARGET); | 1587 __ Jump(code, RelocInfo::CODE_TARGET); |
1607 } | 1588 } |
1608 | 1589 |
1609 | 1590 |
1610 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1591 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1611 Handle<JSObject> holder, | 1592 Handle<JSObject> holder, |
1612 PropertyIndex index, | 1593 PropertyIndex index, |
1613 Handle<Name> name) { | 1594 Handle<Name> name) { |
1614 // ----------- S t a t e ------------- | |
1615 // -- r2 : name | |
1616 // -- lr : return address | |
1617 // ----------------------------------- | |
1618 Label miss; | 1595 Label miss; |
1619 | 1596 |
1620 GenerateNameCheck(name, &miss); | 1597 Register reg = HandlerFrontendHeader( |
1621 | 1598 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1622 const int argc = arguments().immediate(); | |
1623 | |
1624 // Get the receiver of the function from the stack into r0. | |
1625 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | |
1626 // Check that the receiver isn't a smi. | |
1627 __ JumpIfSmi(r0, &miss); | |
1628 | |
1629 // Do the right check and compute the holder register. | |
1630 Register reg = CheckPrototypes( | |
1631 IC::CurrentTypeOf(object, isolate()), | |
1632 r0, holder, r1, r3, r4, name, &miss); | |
1633 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | 1599 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
1634 index.translate(holder), Representation::Tagged()); | 1600 index.translate(holder), Representation::Tagged()); |
1635 | 1601 |
1636 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 1602 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
1637 | 1603 |
1638 // Handle call cache miss. | 1604 HandlerFrontendFooter(&miss); |
1639 __ bind(&miss); | |
1640 GenerateMissBranch(); | |
1641 | 1605 |
1642 // Return the generated code. | 1606 // Return the generated code. |
1643 return GetCode(Code::FAST, name); | 1607 return GetCode(Code::FAST, name); |
1644 } | 1608 } |
1645 | 1609 |
1646 | 1610 |
1647 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1611 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1648 Handle<Object> object, | 1612 Handle<Object> object, |
1649 Handle<JSObject> holder, | 1613 Handle<JSObject> holder, |
1650 Handle<Cell> cell, | 1614 Handle<Cell> cell, |
1651 Handle<JSFunction> function, | 1615 Handle<JSFunction> function, |
1652 Handle<String> name, | 1616 Handle<String> name, |
1653 Code::StubType type) { | 1617 Code::StubType type) { |
1654 Label miss; | 1618 Label miss; |
1655 | 1619 |
1656 // Check that function is still array | 1620 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1657 const int argc = arguments().immediate(); | 1621 if (!cell.is_null()) { |
1658 GenerateNameCheck(name, &miss); | |
1659 Register receiver = r1; | |
1660 | |
1661 if (cell.is_null()) { | |
1662 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | |
1663 | |
1664 // Check that the receiver isn't a smi. | |
1665 __ JumpIfSmi(receiver, &miss); | |
1666 | |
1667 // Check that the maps haven't changed. | |
1668 CheckPrototypes( | |
1669 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1670 r3, r0, r4, name, &miss); | |
1671 } else { | |
1672 ASSERT(cell->value() == *function); | 1622 ASSERT(cell->value() == *function); |
1673 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
1674 &miss); | |
1675 GenerateLoadFunctionFromCell(cell, function, &miss); | 1623 GenerateLoadFunctionFromCell(cell, function, &miss); |
1676 } | 1624 } |
1677 | 1625 |
1678 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1626 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
1679 site->SetElementsKind(GetInitialFastElementsKind()); | 1627 site->SetElementsKind(GetInitialFastElementsKind()); |
1680 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1628 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
1629 const int argc = arguments().immediate(); | |
1681 __ mov(r0, Operand(argc)); | 1630 __ mov(r0, Operand(argc)); |
1682 __ mov(r2, Operand(site_feedback_cell)); | 1631 __ mov(r2, Operand(site_feedback_cell)); |
1683 __ mov(r1, Operand(function)); | 1632 __ mov(r1, Operand(function)); |
1684 | 1633 |
1685 ArrayConstructorStub stub(isolate()); | 1634 ArrayConstructorStub stub(isolate()); |
1686 __ TailCallStub(&stub); | 1635 __ TailCallStub(&stub); |
1687 | 1636 |
1688 __ bind(&miss); | 1637 HandlerFrontendFooter(&miss); |
1689 GenerateMissBranch(); | |
1690 | 1638 |
1691 // Return the generated code. | 1639 // Return the generated code. |
1692 return GetCode(type, name); | 1640 return GetCode(type, name); |
1693 } | 1641 } |
1694 | 1642 |
1695 | 1643 |
1696 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1644 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
1697 Handle<Object> object, | 1645 Handle<Object> object, |
1698 Handle<JSObject> holder, | 1646 Handle<JSObject> holder, |
1699 Handle<Cell> cell, | 1647 Handle<Cell> cell, |
1700 Handle<JSFunction> function, | 1648 Handle<JSFunction> function, |
1701 Handle<String> name, | 1649 Handle<String> name, |
1702 Code::StubType type) { | 1650 Code::StubType type) { |
1703 // ----------- S t a t e ------------- | |
1704 // -- r2 : name | |
1705 // -- lr : return address | |
1706 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1707 // -- ... | |
1708 // -- sp[argc * 4] : receiver | |
1709 // ----------------------------------- | |
1710 | |
1711 // If object is not an array or is observed, bail out to regular call. | 1651 // If object is not an array or is observed, bail out to regular call. |
1712 if (!object->IsJSArray() || | 1652 if (!object->IsJSArray() || |
1713 !cell.is_null() || | 1653 !cell.is_null() || |
1714 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1654 Handle<JSArray>::cast(object)->map()->is_observed()) { |
1715 return Handle<Code>::null(); | 1655 return Handle<Code>::null(); |
1716 } | 1656 } |
1717 | 1657 |
1718 Label miss; | 1658 Label miss; |
1719 GenerateNameCheck(name, &miss); | |
1720 | 1659 |
1721 Register receiver = r1; | 1660 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1722 // Get the receiver from the stack | 1661 Register receiver = r0; |
1662 Register scratch = r1; | |
1663 | |
1723 const int argc = arguments().immediate(); | 1664 const int argc = arguments().immediate(); |
1724 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | |
1725 | |
1726 // Check that the receiver isn't a smi. | |
1727 __ JumpIfSmi(receiver, &miss); | |
1728 | |
1729 // Check that the maps haven't changed. | |
1730 CheckPrototypes( | |
1731 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1732 r3, r0, r4, name, &miss); | |
1733 | |
1734 if (argc == 0) { | 1665 if (argc == 0) { |
1735 // Nothing to do, just return the length. | 1666 // Nothing to do, just return the length. |
1736 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1667 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1737 __ Drop(argc + 1); | 1668 __ Drop(argc + 1); |
1738 __ Ret(); | 1669 __ Ret(); |
1739 } else { | 1670 } else { |
1740 Label call_builtin; | 1671 Label call_builtin; |
1741 | 1672 |
1742 if (argc == 1) { // Otherwise fall through to call the builtin. | 1673 if (argc == 1) { // Otherwise fall through to call the builtin. |
1743 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1674 Label attempt_to_grow_elements, with_write_barrier, check_double; |
1744 | 1675 |
1745 Register elements = r6; | 1676 Register elements = r6; |
1746 Register end_elements = r5; | 1677 Register end_elements = r5; |
1747 // Get the elements array of the object. | 1678 // Get the elements array of the object. |
1748 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1679 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1749 | 1680 |
1750 // Check that the elements are in fast mode and writable. | 1681 // Check that the elements are in fast mode and writable. |
1751 __ CheckMap(elements, | 1682 __ CheckMap(elements, |
1752 r0, | 1683 scratch, |
1753 Heap::kFixedArrayMapRootIndex, | 1684 Heap::kFixedArrayMapRootIndex, |
1754 &check_double, | 1685 &check_double, |
1755 DONT_DO_SMI_CHECK); | 1686 DONT_DO_SMI_CHECK); |
1756 | 1687 |
1757 // Get the array's length into r0 and calculate new length. | 1688 // Get the array's length into scratch and calculate new length. |
1758 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1689 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1759 __ add(r0, r0, Operand(Smi::FromInt(argc))); | 1690 __ add(scratch, scratch, Operand(Smi::FromInt(argc))); |
1760 | 1691 |
1761 // Get the elements' length. | 1692 // Get the elements' length. |
1762 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1693 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1763 | 1694 |
1764 // Check if we could survive without allocation. | 1695 // Check if we could survive without allocation. |
1765 __ cmp(r0, r4); | 1696 __ cmp(scratch, r4); |
1766 __ b(gt, &attempt_to_grow_elements); | 1697 __ b(gt, &attempt_to_grow_elements); |
1767 | 1698 |
1768 // Check if value is a smi. | 1699 // Check if value is a smi. |
1769 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); | 1700 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); |
1770 __ JumpIfNotSmi(r4, &with_write_barrier); | 1701 __ JumpIfNotSmi(r4, &with_write_barrier); |
1771 | 1702 |
1772 // Save new length. | 1703 // Save new length. |
1773 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1704 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1774 | 1705 |
1775 // Store the value. | 1706 // Store the value. |
1776 // We may need a register containing the address end_elements below, | 1707 // We may need a register containing the address end_elements below, |
1777 // so write back the value in end_elements. | 1708 // so write back the value in end_elements. |
1778 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0)); | 1709 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch)); |
1779 const int kEndElementsOffset = | 1710 const int kEndElementsOffset = |
1780 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1711 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
1781 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | 1712 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
1782 | 1713 |
1783 // Check for a smi. | 1714 // Check for a smi. |
1784 __ Drop(argc + 1); | 1715 __ Drop(argc + 1); |
1716 __ mov(r0, scratch); | |
1785 __ Ret(); | 1717 __ Ret(); |
1786 | 1718 |
1787 __ bind(&check_double); | 1719 __ bind(&check_double); |
1788 | 1720 |
1789 // Check that the elements are in fast mode and writable. | 1721 // Check that the elements are in fast mode and writable. |
1790 __ CheckMap(elements, | 1722 __ CheckMap(elements, |
1791 r0, | 1723 scratch, |
1792 Heap::kFixedDoubleArrayMapRootIndex, | 1724 Heap::kFixedDoubleArrayMapRootIndex, |
1793 &call_builtin, | 1725 &call_builtin, |
1794 DONT_DO_SMI_CHECK); | 1726 DONT_DO_SMI_CHECK); |
1795 | 1727 |
1796 // Get the array's length into r0 and calculate new length. | 1728 // Get the array's length into scratch and calculate new length. |
1797 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1729 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1798 __ add(r0, r0, Operand(Smi::FromInt(argc))); | 1730 __ add(scratch, scratch, Operand(Smi::FromInt(argc))); |
1799 | 1731 |
1800 // Get the elements' length. | 1732 // Get the elements' length. |
1801 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1733 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1802 | 1734 |
1803 // Check if we could survive without allocation. | 1735 // Check if we could survive without allocation. |
1804 __ cmp(r0, r4); | 1736 __ cmp(scratch, r4); |
1805 __ b(gt, &call_builtin); | 1737 __ b(gt, &call_builtin); |
1806 | 1738 |
1807 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); | 1739 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); |
1808 __ StoreNumberToDoubleElements(r4, r0, elements, r5, d0, | 1740 __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0, |
1809 &call_builtin, argc * kDoubleSize); | 1741 &call_builtin, argc * kDoubleSize); |
1810 | 1742 |
1811 // Save new length. | 1743 // Save new length. |
1812 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1744 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1813 | 1745 |
1814 // Check for a smi. | |
1815 __ Drop(argc + 1); | 1746 __ Drop(argc + 1); |
1747 __ mov(r0, scratch); | |
1816 __ Ret(); | 1748 __ Ret(); |
1817 | 1749 |
1818 __ bind(&with_write_barrier); | 1750 __ bind(&with_write_barrier); |
1819 | 1751 |
1820 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1752 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1821 | 1753 |
1822 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | 1754 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
1823 Label fast_object, not_fast_object; | 1755 Label fast_object, not_fast_object; |
1824 __ CheckFastObjectElements(r3, r9, ¬_fast_object); | 1756 __ CheckFastObjectElements(r3, r9, ¬_fast_object); |
1825 __ jmp(&fast_object); | 1757 __ jmp(&fast_object); |
(...skipping 30 matching lines...) Expand all Loading... | |
1856 ElementsTransitionGenerator:: | 1788 ElementsTransitionGenerator:: |
1857 GenerateMapChangeElementsTransition(masm(), | 1789 GenerateMapChangeElementsTransition(masm(), |
1858 DONT_TRACK_ALLOCATION_SITE, | 1790 DONT_TRACK_ALLOCATION_SITE, |
1859 NULL); | 1791 NULL); |
1860 __ bind(&fast_object); | 1792 __ bind(&fast_object); |
1861 } else { | 1793 } else { |
1862 __ CheckFastObjectElements(r3, r3, &call_builtin); | 1794 __ CheckFastObjectElements(r3, r3, &call_builtin); |
1863 } | 1795 } |
1864 | 1796 |
1865 // Save new length. | 1797 // Save new length. |
1866 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1798 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1867 | 1799 |
1868 // Store the value. | 1800 // Store the value. |
1869 // We may need a register containing the address end_elements below, | 1801 // We may need a register containing the address end_elements below, |
1870 // so write back the value in end_elements. | 1802 // so write back the value in end_elements. |
1871 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0)); | 1803 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch)); |
1872 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | 1804 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
1873 | 1805 |
1874 __ RecordWrite(elements, | 1806 __ RecordWrite(elements, |
1875 end_elements, | 1807 end_elements, |
1876 r4, | 1808 r4, |
1877 kLRHasNotBeenSaved, | 1809 kLRHasNotBeenSaved, |
1878 kDontSaveFPRegs, | 1810 kDontSaveFPRegs, |
1879 EMIT_REMEMBERED_SET, | 1811 EMIT_REMEMBERED_SET, |
1880 OMIT_SMI_CHECK); | 1812 OMIT_SMI_CHECK); |
1881 __ Drop(argc + 1); | 1813 __ Drop(argc + 1); |
1814 __ mov(r0, scratch); | |
1882 __ Ret(); | 1815 __ Ret(); |
1883 | 1816 |
1884 __ bind(&attempt_to_grow_elements); | 1817 __ bind(&attempt_to_grow_elements); |
1885 // r0: array's length + 1. | 1818 // scratch: array's length + 1. |
1886 | 1819 |
1887 if (!FLAG_inline_new) { | 1820 if (!FLAG_inline_new) { |
1888 __ b(&call_builtin); | 1821 __ b(&call_builtin); |
1889 } | 1822 } |
1890 | 1823 |
1891 __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize)); | 1824 __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize)); |
1892 // Growing elements that are SMI-only requires special handling in case | 1825 // Growing elements that are SMI-only requires special handling in case |
1893 // the new element is non-Smi. For now, delegate to the builtin. | 1826 // the new element is non-Smi. For now, delegate to the builtin. |
1894 Label no_fast_elements_check; | 1827 Label no_fast_elements_check; |
1895 __ JumpIfSmi(r2, &no_fast_elements_check); | 1828 __ JumpIfSmi(r2, &no_fast_elements_check); |
1896 __ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1829 __ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1897 __ CheckFastObjectElements(r9, r9, &call_builtin); | 1830 __ CheckFastObjectElements(r9, r9, &call_builtin); |
1898 __ bind(&no_fast_elements_check); | 1831 __ bind(&no_fast_elements_check); |
1899 | 1832 |
1900 ExternalReference new_space_allocation_top = | 1833 ExternalReference new_space_allocation_top = |
1901 ExternalReference::new_space_allocation_top_address(isolate()); | 1834 ExternalReference::new_space_allocation_top_address(isolate()); |
1902 ExternalReference new_space_allocation_limit = | 1835 ExternalReference new_space_allocation_limit = |
1903 ExternalReference::new_space_allocation_limit_address(isolate()); | 1836 ExternalReference::new_space_allocation_limit_address(isolate()); |
1904 | 1837 |
1905 const int kAllocationDelta = 4; | 1838 const int kAllocationDelta = 4; |
1906 // Load top and check if it is the end of elements. | 1839 // Load top and check if it is the end of elements. |
1907 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0)); | 1840 __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch)); |
1908 __ add(end_elements, end_elements, Operand(kEndElementsOffset)); | 1841 __ add(end_elements, end_elements, Operand(kEndElementsOffset)); |
1909 __ mov(r4, Operand(new_space_allocation_top)); | 1842 __ mov(r4, Operand(new_space_allocation_top)); |
1910 __ ldr(r3, MemOperand(r4)); | 1843 __ ldr(r3, MemOperand(r4)); |
1911 __ cmp(end_elements, r3); | 1844 __ cmp(end_elements, r3); |
1912 __ b(ne, &call_builtin); | 1845 __ b(ne, &call_builtin); |
1913 | 1846 |
1914 __ mov(r9, Operand(new_space_allocation_limit)); | 1847 __ mov(r9, Operand(new_space_allocation_limit)); |
1915 __ ldr(r9, MemOperand(r9)); | 1848 __ ldr(r9, MemOperand(r9)); |
1916 __ add(r3, r3, Operand(kAllocationDelta * kPointerSize)); | 1849 __ add(r3, r3, Operand(kAllocationDelta * kPointerSize)); |
1917 __ cmp(r3, r9); | 1850 __ cmp(r3, r9); |
1918 __ b(hi, &call_builtin); | 1851 __ b(hi, &call_builtin); |
1919 | 1852 |
1920 // We fit and could grow elements. | 1853 // We fit and could grow elements. |
1921 // Update new_space_allocation_top. | 1854 // Update new_space_allocation_top. |
1922 __ str(r3, MemOperand(r4)); | 1855 __ str(r3, MemOperand(r4)); |
1923 // Push the argument. | 1856 // Push the argument. |
1924 __ str(r2, MemOperand(end_elements)); | 1857 __ str(r2, MemOperand(end_elements)); |
1925 // Fill the rest with holes. | 1858 // Fill the rest with holes. |
1926 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); | 1859 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); |
1927 for (int i = 1; i < kAllocationDelta; i++) { | 1860 for (int i = 1; i < kAllocationDelta; i++) { |
1928 __ str(r3, MemOperand(end_elements, i * kPointerSize)); | 1861 __ str(r3, MemOperand(end_elements, i * kPointerSize)); |
1929 } | 1862 } |
1930 | 1863 |
1931 // Update elements' and array's sizes. | 1864 // Update elements' and array's sizes. |
1932 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1865 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1933 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1866 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1934 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); | 1867 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); |
1935 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1868 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1936 | 1869 |
1937 // Elements are in new space, so write barrier is not required. | 1870 // Elements are in new space, so write barrier is not required. |
1938 __ Drop(argc + 1); | 1871 __ Drop(argc + 1); |
1872 __ mov(r0, scratch); | |
1939 __ Ret(); | 1873 __ Ret(); |
1940 } | 1874 } |
1941 __ bind(&call_builtin); | 1875 __ bind(&call_builtin); |
1942 __ TailCallExternalReference( | 1876 __ TailCallExternalReference( |
1943 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | 1877 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); |
1944 } | 1878 } |
1945 | 1879 |
1946 // Handle call cache miss. | 1880 HandlerFrontendFooter(&miss); |
1947 __ bind(&miss); | |
1948 GenerateMissBranch(); | |
1949 | 1881 |
1950 // Return the generated code. | 1882 // Return the generated code. |
1951 return GetCode(type, name); | 1883 return GetCode(type, name); |
1952 } | 1884 } |
1953 | 1885 |
1954 | 1886 |
1955 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1887 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
1956 Handle<Object> object, | 1888 Handle<Object> object, |
1957 Handle<JSObject> holder, | 1889 Handle<JSObject> holder, |
1958 Handle<Cell> cell, | 1890 Handle<Cell> cell, |
1959 Handle<JSFunction> function, | 1891 Handle<JSFunction> function, |
1960 Handle<String> name, | 1892 Handle<String> name, |
1961 Code::StubType type) { | 1893 Code::StubType type) { |
1962 // ----------- S t a t e ------------- | |
1963 // -- r2 : name | |
1964 // -- lr : return address | |
1965 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1966 // -- ... | |
1967 // -- sp[argc * 4] : receiver | |
1968 // ----------------------------------- | |
1969 | |
1970 // If object is not an array or is observed, bail out to regular call. | 1894 // If object is not an array or is observed, bail out to regular call. |
1971 if (!object->IsJSArray() || | 1895 if (!object->IsJSArray() || |
1972 !cell.is_null() || | 1896 !cell.is_null() || |
1973 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1897 Handle<JSArray>::cast(object)->map()->is_observed()) { |
1974 return Handle<Code>::null(); | 1898 return Handle<Code>::null(); |
1975 } | 1899 } |
1976 | 1900 |
1977 Label miss, return_undefined, call_builtin; | 1901 Label miss, return_undefined, call_builtin; |
1978 Register receiver = r1; | 1902 Register receiver = r0; |
1903 Register scratch = r1; | |
1979 Register elements = r3; | 1904 Register elements = r3; |
1980 GenerateNameCheck(name, &miss); | |
1981 | 1905 |
1982 // Get the receiver from the stack | 1906 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1983 const int argc = arguments().immediate(); | |
1984 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | |
1985 // Check that the receiver isn't a smi. | |
1986 __ JumpIfSmi(receiver, &miss); | |
1987 | |
1988 // Check that the maps haven't changed. | |
1989 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
1990 elements, r4, r0, name, &miss); | |
1991 | 1907 |
1992 // Get the elements array of the object. | 1908 // Get the elements array of the object. |
1993 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1909 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1994 | 1910 |
1995 // Check that the elements are in fast mode and writable. | 1911 // Check that the elements are in fast mode and writable. |
1996 __ CheckMap(elements, | 1912 __ CheckMap(elements, |
1997 r0, | 1913 scratch, |
1998 Heap::kFixedArrayMapRootIndex, | 1914 Heap::kFixedArrayMapRootIndex, |
1999 &call_builtin, | 1915 &call_builtin, |
2000 DONT_DO_SMI_CHECK); | 1916 DONT_DO_SMI_CHECK); |
2001 | 1917 |
2002 // Get the array's length into r4 and calculate new length. | 1918 // Get the array's length into r4 and calculate new length. |
2003 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1919 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
2004 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); | 1920 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); |
2005 __ b(lt, &return_undefined); | 1921 __ b(lt, &return_undefined); |
2006 | 1922 |
2007 // Get the last element. | 1923 // Get the last element. |
2008 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); | 1924 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); |
2009 // We can't address the last element in one operation. Compute the more | 1925 // We can't address the last element in one operation. Compute the more |
2010 // expensive shift first, and use an offset later on. | 1926 // expensive shift first, and use an offset later on. |
2011 __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4)); | 1927 __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4)); |
2012 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1928 __ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
2013 __ cmp(r0, r6); | 1929 __ cmp(scratch, r6); |
2014 __ b(eq, &call_builtin); | 1930 __ b(eq, &call_builtin); |
2015 | 1931 |
2016 // Set the array's length. | 1932 // Set the array's length. |
2017 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1933 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
2018 | 1934 |
2019 // Fill with the hole. | 1935 // Fill with the hole. |
2020 __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1936 __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
1937 const int argc = arguments().immediate(); | |
2021 __ Drop(argc + 1); | 1938 __ Drop(argc + 1); |
1939 __ mov(r0, scratch); | |
2022 __ Ret(); | 1940 __ Ret(); |
2023 | 1941 |
2024 __ bind(&return_undefined); | 1942 __ bind(&return_undefined); |
2025 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1943 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
2026 __ Drop(argc + 1); | 1944 __ Drop(argc + 1); |
2027 __ Ret(); | 1945 __ Ret(); |
2028 | 1946 |
2029 __ bind(&call_builtin); | 1947 __ bind(&call_builtin); |
2030 __ TailCallExternalReference( | 1948 __ TailCallExternalReference( |
2031 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | 1949 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); |
2032 | 1950 |
2033 // Handle call cache miss. | 1951 HandlerFrontendFooter(&miss); |
2034 __ bind(&miss); | |
2035 GenerateMissBranch(); | |
2036 | 1952 |
2037 // Return the generated code. | 1953 // Return the generated code. |
2038 return GetCode(type, name); | 1954 return GetCode(type, name); |
2039 } | 1955 } |
2040 | 1956 |
2041 | 1957 |
2042 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1958 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
2043 Handle<Object> object, | 1959 Handle<Object> object, |
2044 Handle<JSObject> holder, | 1960 Handle<JSObject> holder, |
2045 Handle<Cell> cell, | 1961 Handle<Cell> cell, |
2046 Handle<JSFunction> function, | 1962 Handle<JSFunction> function, |
2047 Handle<String> name, | 1963 Handle<String> name, |
2048 Code::StubType type) { | 1964 Code::StubType type) { |
2049 // ----------- S t a t e ------------- | |
2050 // -- r2 : function name | |
2051 // -- lr : return address | |
2052 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2053 // -- ... | |
2054 // -- sp[argc * 4] : receiver | |
2055 // ----------------------------------- | |
2056 | |
2057 // If object is not a string, bail out to regular call. | 1965 // If object is not a string, bail out to regular call. |
2058 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1966 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2059 | 1967 |
2060 const int argc = arguments().immediate(); | |
2061 Label miss; | 1968 Label miss; |
2062 Label name_miss; | 1969 Label name_miss; |
2063 Label index_out_of_range; | 1970 Label index_out_of_range; |
2064 Label* index_out_of_range_label = &index_out_of_range; | 1971 Label* index_out_of_range_label = &index_out_of_range; |
2065 | 1972 |
2066 if (kind_ == Code::CALL_IC && | 1973 if (kind_ == Code::CALL_IC && |
2067 (CallICBase::StringStubState::decode(extra_state_) == | 1974 (CallICBase::StringStubState::decode(extra_state_) == |
2068 DEFAULT_STRING_STUB)) { | 1975 DEFAULT_STRING_STUB)) { |
2069 index_out_of_range_label = &miss; | 1976 index_out_of_range_label = &miss; |
2070 } | 1977 } |
2071 GenerateNameCheck(name, &name_miss); | |
2072 | 1978 |
2073 // Check that the maps starting from the prototype haven't changed. | 1979 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
2074 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
2075 Context::STRING_FUNCTION_INDEX, | |
2076 r0, | |
2077 &miss); | |
2078 ASSERT(!object.is_identical_to(holder)); | |
2079 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
2080 CheckPrototypes( | |
2081 IC::CurrentTypeOf(prototype, isolate()), | |
2082 r0, holder, r1, r3, r4, name, &miss); | |
2083 | 1980 |
2084 Register receiver = r1; | 1981 Register receiver = r0; |
2085 Register index = r4; | 1982 Register index = r4; |
2086 Register result = r0; | 1983 Register result = r1; |
1984 const int argc = arguments().immediate(); | |
2087 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1985 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
2088 if (argc > 0) { | 1986 if (argc > 0) { |
2089 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1987 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2090 } else { | 1988 } else { |
2091 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1989 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2092 } | 1990 } |
2093 | 1991 |
2094 StringCharCodeAtGenerator generator(receiver, | 1992 StringCharCodeAtGenerator generator(receiver, |
2095 index, | 1993 index, |
2096 result, | 1994 result, |
2097 &miss, // When not a string. | 1995 &miss, // When not a string. |
2098 &miss, // When not a number. | 1996 &miss, // When not a number. |
2099 index_out_of_range_label, | 1997 index_out_of_range_label, |
2100 STRING_INDEX_IS_NUMBER); | 1998 STRING_INDEX_IS_NUMBER); |
2101 generator.GenerateFast(masm()); | 1999 generator.GenerateFast(masm()); |
2102 __ Drop(argc + 1); | 2000 __ Drop(argc + 1); |
2001 __ mov(r0, result); | |
2103 __ Ret(); | 2002 __ Ret(); |
2104 | 2003 |
2105 StubRuntimeCallHelper call_helper; | 2004 StubRuntimeCallHelper call_helper; |
2106 generator.GenerateSlow(masm(), call_helper); | 2005 generator.GenerateSlow(masm(), call_helper); |
2107 | 2006 |
2108 if (index_out_of_range.is_linked()) { | 2007 if (index_out_of_range.is_linked()) { |
2109 __ bind(&index_out_of_range); | 2008 __ bind(&index_out_of_range); |
2110 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 2009 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
2111 __ Drop(argc + 1); | 2010 __ Drop(argc + 1); |
2112 __ Ret(); | 2011 __ Ret(); |
(...skipping 10 matching lines...) Expand all Loading... | |
2123 } | 2022 } |
2124 | 2023 |
2125 | 2024 |
2126 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2025 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2127 Handle<Object> object, | 2026 Handle<Object> object, |
2128 Handle<JSObject> holder, | 2027 Handle<JSObject> holder, |
2129 Handle<Cell> cell, | 2028 Handle<Cell> cell, |
2130 Handle<JSFunction> function, | 2029 Handle<JSFunction> function, |
2131 Handle<String> name, | 2030 Handle<String> name, |
2132 Code::StubType type) { | 2031 Code::StubType type) { |
2133 // ----------- S t a t e ------------- | |
2134 // -- r2 : function name | |
2135 // -- lr : return address | |
2136 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2137 // -- ... | |
2138 // -- sp[argc * 4] : receiver | |
2139 // ----------------------------------- | |
2140 | |
2141 // If object is not a string, bail out to regular call. | 2032 // If object is not a string, bail out to regular call. |
2142 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2033 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2143 | 2034 |
2144 const int argc = arguments().immediate(); | 2035 const int argc = arguments().immediate(); |
2145 Label miss; | 2036 Label miss; |
2146 Label name_miss; | 2037 Label name_miss; |
2147 Label index_out_of_range; | 2038 Label index_out_of_range; |
2148 Label* index_out_of_range_label = &index_out_of_range; | 2039 Label* index_out_of_range_label = &index_out_of_range; |
2149 if (kind_ == Code::CALL_IC && | 2040 if (kind_ == Code::CALL_IC && |
2150 (CallICBase::StringStubState::decode(extra_state_) == | 2041 (CallICBase::StringStubState::decode(extra_state_) == |
2151 DEFAULT_STRING_STUB)) { | 2042 DEFAULT_STRING_STUB)) { |
2152 index_out_of_range_label = &miss; | 2043 index_out_of_range_label = &miss; |
2153 } | 2044 } |
2154 GenerateNameCheck(name, &name_miss); | |
2155 | 2045 |
2156 // Check that the maps starting from the prototype haven't changed. | 2046 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
2157 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
2158 Context::STRING_FUNCTION_INDEX, | |
2159 r0, | |
2160 &miss); | |
2161 ASSERT(!object.is_identical_to(holder)); | |
2162 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
2163 CheckPrototypes( | |
2164 IC::CurrentTypeOf(prototype, isolate()), | |
2165 r0, holder, r1, r3, r4, name, &miss); | |
2166 | 2047 |
2167 Register receiver = r0; | 2048 Register receiver = r0; |
2168 Register index = r4; | 2049 Register index = r4; |
2169 Register scratch = r3; | 2050 Register scratch = r3; |
2170 Register result = r0; | 2051 Register result = r1; |
2171 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | |
2172 if (argc > 0) { | 2052 if (argc > 0) { |
2173 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 2053 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2174 } else { | 2054 } else { |
2175 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2055 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2176 } | 2056 } |
2177 | 2057 |
2178 StringCharAtGenerator generator(receiver, | 2058 StringCharAtGenerator generator(receiver, |
2179 index, | 2059 index, |
2180 scratch, | 2060 scratch, |
2181 result, | 2061 result, |
2182 &miss, // When not a string. | 2062 &miss, // When not a string. |
2183 &miss, // When not a number. | 2063 &miss, // When not a number. |
2184 index_out_of_range_label, | 2064 index_out_of_range_label, |
2185 STRING_INDEX_IS_NUMBER); | 2065 STRING_INDEX_IS_NUMBER); |
2186 generator.GenerateFast(masm()); | 2066 generator.GenerateFast(masm()); |
2187 __ Drop(argc + 1); | 2067 __ Drop(argc + 1); |
2068 __ mov(r0, result); | |
2188 __ Ret(); | 2069 __ Ret(); |
2189 | 2070 |
2190 StubRuntimeCallHelper call_helper; | 2071 StubRuntimeCallHelper call_helper; |
2191 generator.GenerateSlow(masm(), call_helper); | 2072 generator.GenerateSlow(masm(), call_helper); |
2192 | 2073 |
2193 if (index_out_of_range.is_linked()) { | 2074 if (index_out_of_range.is_linked()) { |
2194 __ bind(&index_out_of_range); | 2075 __ bind(&index_out_of_range); |
2195 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 2076 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
2196 __ Drop(argc + 1); | 2077 __ Drop(argc + 1); |
2197 __ Ret(); | 2078 __ Ret(); |
(...skipping 10 matching lines...) Expand all Loading... | |
2208 } | 2089 } |
2209 | 2090 |
2210 | 2091 |
2211 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2092 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2212 Handle<Object> object, | 2093 Handle<Object> object, |
2213 Handle<JSObject> holder, | 2094 Handle<JSObject> holder, |
2214 Handle<Cell> cell, | 2095 Handle<Cell> cell, |
2215 Handle<JSFunction> function, | 2096 Handle<JSFunction> function, |
2216 Handle<String> name, | 2097 Handle<String> name, |
2217 Code::StubType type) { | 2098 Code::StubType type) { |
2218 // ----------- S t a t e ------------- | |
2219 // -- r2 : function name | |
2220 // -- lr : return address | |
2221 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2222 // -- ... | |
2223 // -- sp[argc * 4] : receiver | |
2224 // ----------------------------------- | |
2225 | |
2226 const int argc = arguments().immediate(); | 2099 const int argc = arguments().immediate(); |
2227 | 2100 |
2228 // If the object is not a JSObject or we got an unexpected number of | 2101 // If the object is not a JSObject or we got an unexpected number of |
2229 // arguments, bail out to the regular call. | 2102 // arguments, bail out to the regular call. |
2230 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2103 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2231 | 2104 |
2232 Label miss; | 2105 Label miss; |
2233 GenerateNameCheck(name, &miss); | |
2234 | 2106 |
2235 if (cell.is_null()) { | 2107 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2236 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2108 if (!cell.is_null()) { |
2237 | |
2238 __ JumpIfSmi(r1, &miss); | |
2239 | |
2240 CheckPrototypes( | |
2241 IC::CurrentTypeOf(object, isolate()), | |
2242 r1, holder, r0, r3, r4, name, &miss); | |
2243 } else { | |
2244 ASSERT(cell->value() == *function); | 2109 ASSERT(cell->value() == *function); |
2245 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2246 &miss); | |
2247 GenerateLoadFunctionFromCell(cell, function, &miss); | 2110 GenerateLoadFunctionFromCell(cell, function, &miss); |
2248 } | 2111 } |
2249 | 2112 |
2250 // Load the char code argument. | 2113 // Load the char code argument. |
2251 Register code = r1; | 2114 Register code = r1; |
2252 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 2115 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
2253 | 2116 |
2254 // Check the code is a smi. | 2117 // Check the code is a smi. |
2255 Label slow; | 2118 Label slow; |
2256 __ JumpIfNotSmi(code, &slow); | 2119 __ JumpIfNotSmi(code, &slow); |
2257 | 2120 |
2258 // Convert the smi code to uint16. | 2121 // Convert the smi code to uint16. |
2259 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 2122 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
2260 | 2123 |
2261 StringCharFromCodeGenerator generator(code, r0); | 2124 StringCharFromCodeGenerator generator(code, r0); |
2262 generator.GenerateFast(masm()); | 2125 generator.GenerateFast(masm()); |
2263 __ Drop(argc + 1); | 2126 __ Drop(argc + 1); |
2264 __ Ret(); | 2127 __ Ret(); |
2265 | 2128 |
2266 StubRuntimeCallHelper call_helper; | 2129 StubRuntimeCallHelper call_helper; |
2267 generator.GenerateSlow(masm(), call_helper); | 2130 generator.GenerateSlow(masm(), call_helper); |
2268 | 2131 |
2269 // Tail call the full function. We do not have to patch the receiver | 2132 // Tail call the full function. We do not have to patch the receiver |
2270 // because the function makes no use of it. | 2133 // because the function makes no use of it. |
2271 __ bind(&slow); | 2134 __ bind(&slow); |
2272 ParameterCount expected(function); | 2135 ParameterCount expected(function); |
2273 __ InvokeFunction(function, expected, arguments(), | 2136 __ InvokeFunction(function, expected, arguments(), |
2274 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2137 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2275 | 2138 |
2276 __ bind(&miss); | 2139 HandlerFrontendFooter(&miss); |
2277 // r2: function name. | |
2278 GenerateMissBranch(); | |
2279 | 2140 |
2280 // Return the generated code. | 2141 // Return the generated code. |
2281 return GetCode(type, name); | 2142 return GetCode(type, name); |
2282 } | 2143 } |
2283 | 2144 |
2284 | 2145 |
2285 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2146 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2286 Handle<Object> object, | 2147 Handle<Object> object, |
2287 Handle<JSObject> holder, | 2148 Handle<JSObject> holder, |
2288 Handle<Cell> cell, | 2149 Handle<Cell> cell, |
2289 Handle<JSFunction> function, | 2150 Handle<JSFunction> function, |
2290 Handle<String> name, | 2151 Handle<String> name, |
2291 Code::StubType type) { | 2152 Code::StubType type) { |
2292 // ----------- S t a t e ------------- | |
2293 // -- r2 : function name | |
2294 // -- lr : return address | |
2295 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2296 // -- ... | |
2297 // -- sp[argc * 4] : receiver | |
2298 // ----------------------------------- | |
2299 | |
2300 const int argc = arguments().immediate(); | 2153 const int argc = arguments().immediate(); |
2301 // If the object is not a JSObject or we got an unexpected number of | 2154 // If the object is not a JSObject or we got an unexpected number of |
2302 // arguments, bail out to the regular call. | 2155 // arguments, bail out to the regular call. |
2303 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2156 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2304 | 2157 |
2305 Label miss, slow; | 2158 Label miss, slow; |
2306 GenerateNameCheck(name, &miss); | |
2307 | 2159 |
2308 if (cell.is_null()) { | 2160 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2309 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2161 if (!cell.is_null()) { |
2310 __ JumpIfSmi(r1, &miss); | |
2311 CheckPrototypes( | |
2312 IC::CurrentTypeOf(object, isolate()), | |
2313 r1, holder, r0, r3, r4, name, &miss); | |
2314 } else { | |
2315 ASSERT(cell->value() == *function); | 2162 ASSERT(cell->value() == *function); |
2316 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2317 &miss); | |
2318 GenerateLoadFunctionFromCell(cell, function, &miss); | 2163 GenerateLoadFunctionFromCell(cell, function, &miss); |
2319 } | 2164 } |
2320 | 2165 |
2321 // Load the (only) argument into r0. | 2166 // Load the (only) argument into r0. |
2322 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2167 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
2323 | 2168 |
2324 // If the argument is a smi, just return. | 2169 // If the argument is a smi, just return. |
2325 __ SmiTst(r0); | 2170 __ SmiTst(r0); |
2326 __ Drop(argc + 1, eq); | 2171 __ Drop(argc + 1, eq); |
2327 __ Ret(eq); | 2172 __ Ret(eq); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2376 __ Drop(argc + 1); | 2221 __ Drop(argc + 1); |
2377 __ Ret(); | 2222 __ Ret(); |
2378 | 2223 |
2379 __ bind(&slow); | 2224 __ bind(&slow); |
2380 // Tail call the full function. We do not have to patch the receiver | 2225 // Tail call the full function. We do not have to patch the receiver |
2381 // because the function makes no use of it. | 2226 // because the function makes no use of it. |
2382 ParameterCount expected(function); | 2227 ParameterCount expected(function); |
2383 __ InvokeFunction(function, expected, arguments(), | 2228 __ InvokeFunction(function, expected, arguments(), |
2384 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2229 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2385 | 2230 |
2386 __ bind(&miss); | 2231 HandlerFrontendFooter(&miss); |
2387 // r2: function name. | |
2388 GenerateMissBranch(); | |
2389 | 2232 |
2390 // Return the generated code. | 2233 // Return the generated code. |
2391 return GetCode(type, name); | 2234 return GetCode(type, name); |
2392 } | 2235 } |
2393 | 2236 |
2394 | 2237 |
2395 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2238 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2396 Handle<Object> object, | 2239 Handle<Object> object, |
2397 Handle<JSObject> holder, | 2240 Handle<JSObject> holder, |
2398 Handle<Cell> cell, | 2241 Handle<Cell> cell, |
2399 Handle<JSFunction> function, | 2242 Handle<JSFunction> function, |
2400 Handle<String> name, | 2243 Handle<String> name, |
2401 Code::StubType type) { | 2244 Code::StubType type) { |
2402 // ----------- S t a t e ------------- | |
2403 // -- r2 : function name | |
2404 // -- lr : return address | |
2405 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
2406 // -- ... | |
2407 // -- sp[argc * 4] : receiver | |
2408 // ----------------------------------- | |
2409 | |
2410 const int argc = arguments().immediate(); | 2245 const int argc = arguments().immediate(); |
2411 // If the object is not a JSObject or we got an unexpected number of | 2246 // If the object is not a JSObject or we got an unexpected number of |
2412 // arguments, bail out to the regular call. | 2247 // arguments, bail out to the regular call. |
2413 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2248 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2414 | 2249 |
2415 Label miss; | 2250 Label miss; |
2416 GenerateNameCheck(name, &miss); | 2251 |
2417 if (cell.is_null()) { | 2252 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2418 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2253 if (!cell.is_null()) { |
2419 __ JumpIfSmi(r1, &miss); | |
2420 CheckPrototypes( | |
2421 IC::CurrentTypeOf(object, isolate()), | |
2422 r1, holder, r0, r3, r4, name, &miss); | |
2423 } else { | |
2424 ASSERT(cell->value() == *function); | 2254 ASSERT(cell->value() == *function); |
2425 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
2426 &miss); | |
2427 GenerateLoadFunctionFromCell(cell, function, &miss); | 2255 GenerateLoadFunctionFromCell(cell, function, &miss); |
2428 } | 2256 } |
2429 | 2257 |
2430 // Load the (only) argument into r0. | 2258 // Load the (only) argument into r0. |
2431 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2259 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
2432 | 2260 |
2433 // Check if the argument is a smi. | 2261 // Check if the argument is a smi. |
2434 Label not_smi; | 2262 Label not_smi; |
2435 __ JumpIfNotSmi(r0, ¬_smi); | 2263 __ JumpIfNotSmi(r0, ¬_smi); |
2436 | 2264 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2476 __ Drop(argc + 1); | 2304 __ Drop(argc + 1); |
2477 __ Ret(); | 2305 __ Ret(); |
2478 | 2306 |
2479 // Tail call the full function. We do not have to patch the receiver | 2307 // Tail call the full function. We do not have to patch the receiver |
2480 // because the function makes no use of it. | 2308 // because the function makes no use of it. |
2481 __ bind(&slow); | 2309 __ bind(&slow); |
2482 ParameterCount expected(function); | 2310 ParameterCount expected(function); |
2483 __ InvokeFunction(function, expected, arguments(), | 2311 __ InvokeFunction(function, expected, arguments(), |
2484 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2312 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2485 | 2313 |
2486 __ bind(&miss); | 2314 HandlerFrontendFooter(&miss); |
2487 // r2: function name. | |
2488 GenerateMissBranch(); | |
2489 | 2315 |
2490 // Return the generated code. | 2316 // Return the generated code. |
2491 return GetCode(type, name); | 2317 return GetCode(type, name); |
2492 } | 2318 } |
2493 | 2319 |
2494 | 2320 |
2495 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2321 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2496 const CallOptimization& optimization, | 2322 const CallOptimization& optimization, |
2497 Handle<Object> object, | 2323 Handle<Object> object, |
2498 Handle<JSObject> holder, | 2324 Handle<JSObject> holder, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2550 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2376 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
2551 __ cmp(object, ip); | 2377 __ cmp(object, ip); |
2552 __ b(eq, &success); | 2378 __ b(eq, &success); |
2553 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2379 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
2554 __ cmp(object, ip); | 2380 __ cmp(object, ip); |
2555 __ b(ne, miss); | 2381 __ b(ne, miss); |
2556 __ bind(&success); | 2382 __ bind(&success); |
2557 } | 2383 } |
2558 | 2384 |
2559 | 2385 |
2560 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2386 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2561 Handle<JSObject> holder, | 2387 if (object->IsGlobalObject()) { |
2562 Handle<Name> name, | 2388 const int argc = arguments().immediate(); |
2563 CheckType check) { | 2389 const int receiver_offset = argc * kPointerSize; |
2390 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | |
2391 __ str(r3, MemOperand(sp, receiver_offset)); | |
2392 } | |
2393 } | |
2394 | |
2395 | |
2396 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | |
2397 Handle<JSObject> holder, | |
2398 Handle<Name> name, | |
2399 CheckType check, | |
2400 Label* miss) { | |
2564 // ----------- S t a t e ------------- | 2401 // ----------- S t a t e ------------- |
2565 // -- r2 : name | 2402 // -- r2 : name |
2566 // -- lr : return address | 2403 // -- lr : return address |
2567 // ----------------------------------- | 2404 // ----------------------------------- |
2568 Label miss; | 2405 GenerateNameCheck(name, miss); |
2569 GenerateNameCheck(name, &miss); | 2406 |
2407 Register reg = r0; | |
2570 | 2408 |
2571 // Get the receiver from the stack | 2409 // Get the receiver from the stack |
2572 const int argc = arguments().immediate(); | 2410 const int argc = arguments().immediate(); |
2573 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2411 const int receiver_offset = argc * kPointerSize; |
2412 __ ldr(r0, MemOperand(sp, receiver_offset)); | |
2574 | 2413 |
2575 // Check that the receiver isn't a smi. | 2414 // Check that the receiver isn't a smi. |
2576 if (check != NUMBER_CHECK) { | 2415 if (check != NUMBER_CHECK) { |
2577 __ JumpIfSmi(r1, &miss); | 2416 __ JumpIfSmi(r0, miss); |
2578 } | 2417 } |
2579 | 2418 |
2580 // Make sure that it's okay not to patch the on stack receiver | 2419 // Make sure that it's okay not to patch the on stack receiver |
2581 // unless we're doing a receiver map check. | 2420 // unless we're doing a receiver map check. |
2582 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2421 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2583 switch (check) { | 2422 switch (check) { |
2584 case RECEIVER_MAP_CHECK: | 2423 case RECEIVER_MAP_CHECK: |
2585 __ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3); | 2424 __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3); |
2586 | 2425 |
2587 // Check that the maps haven't changed. | 2426 // Check that the maps haven't changed. |
2588 CheckPrototypes( | 2427 reg = CheckPrototypes( |
2589 IC::CurrentTypeOf(object, isolate()), | 2428 IC::CurrentTypeOf(object, isolate()), |
2590 r1, holder, r0, r3, r4, name, &miss); | 2429 reg, holder, r1, r3, r4, name, miss); |
2591 | |
2592 // Patch the receiver on the stack with the global proxy if | |
2593 // necessary. | |
2594 if (object->IsGlobalObject()) { | |
2595 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | |
2596 __ str(r3, MemOperand(sp, argc * kPointerSize)); | |
2597 } | |
2598 break; | 2430 break; |
2599 | 2431 |
2600 case STRING_CHECK: { | 2432 case STRING_CHECK: { |
2601 // Check that the object is a string. | 2433 // Check that the object is a string. |
2602 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2434 __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE); |
2603 __ b(ge, &miss); | 2435 __ b(ge, miss); |
2604 // Check that the maps starting from the prototype haven't changed. | 2436 // Check that the maps starting from the prototype haven't changed. |
2605 GenerateDirectLoadGlobalFunctionPrototype( | 2437 GenerateDirectLoadGlobalFunctionPrototype( |
2606 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2438 masm(), Context::STRING_FUNCTION_INDEX, r1, miss); |
2607 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2608 CheckPrototypes( | |
2609 IC::CurrentTypeOf(prototype, isolate()), | |
2610 r0, holder, r3, r1, r4, name, &miss); | |
2611 break; | 2439 break; |
2612 } | 2440 } |
2613 case SYMBOL_CHECK: { | 2441 case SYMBOL_CHECK: { |
2614 // Check that the object is a symbol. | 2442 // Check that the object is a symbol. |
2615 __ CompareObjectType(r1, r1, r3, SYMBOL_TYPE); | 2443 __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE); |
2616 __ b(ne, &miss); | 2444 __ b(ne, miss); |
2617 // Check that the maps starting from the prototype haven't changed. | 2445 // Check that the maps starting from the prototype haven't changed. |
2618 GenerateDirectLoadGlobalFunctionPrototype( | 2446 GenerateDirectLoadGlobalFunctionPrototype( |
2619 masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss); | 2447 masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss); |
2620 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2621 CheckPrototypes( | |
2622 IC::CurrentTypeOf(prototype, isolate()), | |
2623 r0, holder, r3, r1, r4, name, &miss); | |
2624 break; | 2448 break; |
2625 } | 2449 } |
2626 case NUMBER_CHECK: { | 2450 case NUMBER_CHECK: { |
2627 Label fast; | 2451 Label fast; |
2628 // Check that the object is a smi or a heap number. | 2452 // Check that the object is a smi or a heap number. |
2629 __ JumpIfSmi(r1, &fast); | 2453 __ JumpIfSmi(reg, &fast); |
2630 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2454 __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE); |
2631 __ b(ne, &miss); | 2455 __ b(ne, miss); |
2632 __ bind(&fast); | 2456 __ bind(&fast); |
2633 // Check that the maps starting from the prototype haven't changed. | 2457 // Check that the maps starting from the prototype haven't changed. |
2634 GenerateDirectLoadGlobalFunctionPrototype( | 2458 GenerateDirectLoadGlobalFunctionPrototype( |
2635 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2459 masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss); |
2636 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2637 CheckPrototypes( | |
2638 IC::CurrentTypeOf(prototype, isolate()), | |
2639 r0, holder, r3, r1, r4, name, &miss); | |
2640 break; | 2460 break; |
2641 } | 2461 } |
2642 case BOOLEAN_CHECK: { | 2462 case BOOLEAN_CHECK: { |
2643 GenerateBooleanCheck(r1, &miss); | 2463 GenerateBooleanCheck(reg, miss); |
2644 | 2464 |
2645 // Check that the maps starting from the prototype haven't changed. | 2465 // Check that the maps starting from the prototype haven't changed. |
2646 GenerateDirectLoadGlobalFunctionPrototype( | 2466 GenerateDirectLoadGlobalFunctionPrototype( |
2647 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); | 2467 masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss); |
2648 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
2649 CheckPrototypes( | |
2650 IC::CurrentTypeOf(prototype, isolate()), | |
2651 r0, holder, r3, r1, r4, name, &miss); | |
2652 break; | 2468 break; |
2653 } | 2469 } |
2654 } | 2470 } |
2655 | 2471 |
2656 Label success; | 2472 if (check != RECEIVER_MAP_CHECK) { |
2657 __ b(&success); | 2473 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2474 reg = CheckPrototypes( | |
2475 IC::CurrentTypeOf(prototype, isolate()), | |
2476 r1, holder, r1, r3, r4, name, miss); | |
2477 } | |
2658 | 2478 |
2659 // Handle call cache miss. | 2479 return reg; |
2660 __ bind(&miss); | |
2661 GenerateMissBranch(); | |
2662 | |
2663 __ bind(&success); | |
2664 } | 2480 } |
2665 | 2481 |
2666 | 2482 |
2667 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2483 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2668 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2484 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2669 ? CALL_AS_FUNCTION | 2485 ? CALL_AS_FUNCTION |
2670 : CALL_AS_METHOD; | 2486 : CALL_AS_METHOD; |
2671 ParameterCount expected(function); | 2487 ParameterCount expected(function); |
2672 __ InvokeFunction(function, expected, arguments(), | 2488 __ InvokeFunction(function, expected, arguments(), |
2673 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2489 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2674 } | 2490 } |
2675 | 2491 |
2676 | 2492 |
2677 Handle<Code> CallStubCompiler::CompileCallConstant( | 2493 Handle<Code> CallStubCompiler::CompileCallConstant( |
2678 Handle<Object> object, | 2494 Handle<Object> object, |
2679 Handle<JSObject> holder, | 2495 Handle<JSObject> holder, |
2680 Handle<Name> name, | 2496 Handle<Name> name, |
2681 CheckType check, | 2497 CheckType check, |
2682 Handle<JSFunction> function) { | 2498 Handle<JSFunction> function) { |
2683 if (HasCustomCallGenerator(function)) { | 2499 if (HasCustomCallGenerator(function)) { |
2684 Handle<Code> code = CompileCustomCall(object, holder, | 2500 Handle<Code> code = CompileCustomCall(object, holder, |
2685 Handle<Cell>::null(), | 2501 Handle<Cell>::null(), |
2686 function, Handle<String>::cast(name), | 2502 function, Handle<String>::cast(name), |
2687 Code::FAST); | 2503 Code::FAST); |
2688 // A null handle means bail out to the regular compiler code below. | 2504 // A null handle means bail out to the regular compiler code below. |
2689 if (!code.is_null()) return code; | 2505 if (!code.is_null()) return code; |
2690 } | 2506 } |
2691 | 2507 |
2692 CompileHandlerFrontend(object, holder, name, check); | 2508 Label miss; |
2509 HandlerFrontendHeader(object, holder, name, check, &miss); | |
2510 PatchGlobalProxy(object); | |
2693 CompileHandlerBackend(function); | 2511 CompileHandlerBackend(function); |
2512 HandlerFrontendFooter(&miss); | |
2694 | 2513 |
2695 // Return the generated code. | 2514 // Return the generated code. |
2696 return GetCode(function); | 2515 return GetCode(function); |
2697 } | 2516 } |
2698 | 2517 |
2699 | 2518 |
2700 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2519 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2701 Handle<JSObject> holder, | 2520 Handle<JSObject> holder, |
2702 Handle<Name> name) { | 2521 Handle<Name> name) { |
2703 // ----------- S t a t e ------------- | |
2704 // -- r2 : name | |
2705 // -- lr : return address | |
2706 // ----------------------------------- | |
2707 Label miss; | 2522 Label miss; |
2708 GenerateNameCheck(name, &miss); | 2523 GenerateNameCheck(name, &miss); |
2709 | 2524 |
2710 // Get the number of arguments. | 2525 // Get the number of arguments. |
2711 const int argc = arguments().immediate(); | 2526 const int argc = arguments().immediate(); |
2712 LookupResult lookup(isolate()); | 2527 LookupResult lookup(isolate()); |
2713 LookupPostInterceptor(holder, name, &lookup); | 2528 LookupPostInterceptor(holder, name, &lookup); |
2714 | 2529 |
2715 // Get the receiver from the stack. | 2530 // Get the receiver from the stack. |
2716 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2531 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
(...skipping 17 matching lines...) Expand all Loading... | |
2734 return GetCode(Code::FAST, name); | 2549 return GetCode(Code::FAST, name); |
2735 } | 2550 } |
2736 | 2551 |
2737 | 2552 |
2738 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2553 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2739 Handle<JSObject> object, | 2554 Handle<JSObject> object, |
2740 Handle<GlobalObject> holder, | 2555 Handle<GlobalObject> holder, |
2741 Handle<PropertyCell> cell, | 2556 Handle<PropertyCell> cell, |
2742 Handle<JSFunction> function, | 2557 Handle<JSFunction> function, |
2743 Handle<Name> name) { | 2558 Handle<Name> name) { |
2744 // ----------- S t a t e ------------- | |
2745 // -- r2 : name | |
2746 // -- lr : return address | |
2747 // ----------------------------------- | |
2748 if (HasCustomCallGenerator(function)) { | 2559 if (HasCustomCallGenerator(function)) { |
2749 Handle<Code> code = CompileCustomCall( | 2560 Handle<Code> code = CompileCustomCall( |
2750 object, holder, cell, function, Handle<String>::cast(name), | 2561 object, holder, cell, function, Handle<String>::cast(name), |
2751 Code::NORMAL); | 2562 Code::NORMAL); |
2752 // A null handle means bail out to the regular compiler code below. | 2563 // A null handle means bail out to the regular compiler code below. |
2753 if (!code.is_null()) return code; | 2564 if (!code.is_null()) return code; |
2754 } | 2565 } |
2755 | 2566 |
2756 Label miss; | 2567 Label miss; |
2757 GenerateNameCheck(name, &miss); | 2568 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2758 | |
2759 // Get the number of arguments. | |
2760 const int argc = arguments().immediate(); | |
2761 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
2762 GenerateLoadFunctionFromCell(cell, function, &miss); | 2569 GenerateLoadFunctionFromCell(cell, function, &miss); |
2763 | 2570 PatchGlobalProxy(object); |
2764 // Patch the receiver on the stack with the global proxy if | |
2765 // necessary. | |
2766 if (object->IsGlobalObject()) { | |
2767 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | |
2768 __ str(r3, MemOperand(sp, argc * kPointerSize)); | |
2769 } | |
2770 | 2571 |
2771 // Set up the context (function already in r1). | 2572 // Set up the context (function already in r1). |
2772 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2573 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
2773 | 2574 |
2774 // Jump to the cached code (tail call). | 2575 // Jump to the cached code (tail call). |
2775 Counters* counters = isolate()->counters(); | 2576 Counters* counters = isolate()->counters(); |
2776 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2577 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
2777 ParameterCount expected(function->shared()->formal_parameter_count()); | 2578 ParameterCount expected(function->shared()->formal_parameter_count()); |
2778 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2579 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2779 ? CALL_AS_FUNCTION | 2580 ? CALL_AS_FUNCTION |
2780 : CALL_AS_METHOD; | 2581 : CALL_AS_METHOD; |
2781 // We call indirectly through the code field in the function to | 2582 // We call indirectly through the code field in the function to |
2782 // allow recompilation to take effect without changing any of the | 2583 // allow recompilation to take effect without changing any of the |
2783 // call sites. | 2584 // call sites. |
2784 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2585 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
2785 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | 2586 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, |
2786 NullCallWrapper(), call_kind); | 2587 NullCallWrapper(), call_kind); |
2787 | 2588 |
2788 // Handle call cache miss. | 2589 HandlerFrontendFooter(&miss); |
2789 __ bind(&miss); | |
2790 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); | |
2791 GenerateMissBranch(); | |
2792 | 2590 |
2793 // Return the generated code. | 2591 // Return the generated code. |
2794 return GetCode(Code::NORMAL, name); | 2592 return GetCode(Code::NORMAL, name); |
2795 } | 2593 } |
2796 | 2594 |
2797 | 2595 |
2798 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2596 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2799 Handle<JSObject> object, | 2597 Handle<JSObject> object, |
2800 Handle<JSObject> holder, | 2598 Handle<JSObject> holder, |
2801 Handle<Name> name, | 2599 Handle<Name> name, |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3175 // ----------------------------------- | 2973 // ----------------------------------- |
3176 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2974 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
3177 } | 2975 } |
3178 | 2976 |
3179 | 2977 |
3180 #undef __ | 2978 #undef __ |
3181 | 2979 |
3182 } } // namespace v8::internal | 2980 } } // namespace v8::internal |
3183 | 2981 |
3184 #endif // V8_TARGET_ARCH_ARM | 2982 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |