Chromium Code Reviews| 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 |