| 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 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 | 1100 |
| 1101 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1101 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1102 __ Jump(code, RelocInfo::CODE_TARGET); | 1102 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1103 } | 1103 } |
| 1104 | 1104 |
| 1105 | 1105 |
| 1106 #undef __ | 1106 #undef __ |
| 1107 #define __ ACCESS_MASM(masm()) | 1107 #define __ ACCESS_MASM(masm()) |
| 1108 | 1108 |
| 1109 | 1109 |
| 1110 Register StubCompiler::CheckPrototypes(Handle<Type> type, | 1110 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, |
| 1111 Register object_reg, | 1111 Register object_reg, |
| 1112 Handle<JSObject> holder, | 1112 Handle<JSObject> holder, |
| 1113 Register holder_reg, | 1113 Register holder_reg, |
| 1114 Register scratch1, | 1114 Register scratch1, |
| 1115 Register scratch2, | 1115 Register scratch2, |
| 1116 Handle<Name> name, | 1116 Handle<Name> name, |
| 1117 int save_at_depth, | 1117 int save_at_depth, |
| 1118 Label* miss, | 1118 Label* miss, |
| 1119 PrototypeCheckType check) { | 1119 PrototypeCheckType check) { |
| 1120 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 1120 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 Label success; | 1246 Label success; |
| 1247 __ Branch(&success); | 1247 __ Branch(&success); |
| 1248 GenerateRestoreName(masm(), miss, name); | 1248 GenerateRestoreName(masm(), miss, name); |
| 1249 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1249 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1250 __ bind(&success); | 1250 __ bind(&success); |
| 1251 } | 1251 } |
| 1252 } | 1252 } |
| 1253 | 1253 |
| 1254 | 1254 |
| 1255 Register LoadStubCompiler::CallbackHandlerFrontend( | 1255 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1256 Handle<Type> type, | 1256 Handle<HeapType> type, |
| 1257 Register object_reg, | 1257 Register object_reg, |
| 1258 Handle<JSObject> holder, | 1258 Handle<JSObject> holder, |
| 1259 Handle<Name> name, | 1259 Handle<Name> name, |
| 1260 Handle<Object> callback) { | 1260 Handle<Object> callback) { |
| 1261 Label miss; | 1261 Label miss; |
| 1262 | 1262 |
| 1263 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 1263 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1264 | 1264 |
| 1265 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1265 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1266 ASSERT(!reg.is(scratch2())); | 1266 ASSERT(!reg.is(scratch2())); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 index.translate(holder), Representation::Tagged()); | 1549 index.translate(holder), Representation::Tagged()); |
| 1550 GenerateJumpFunction(object, a1, &miss); | 1550 GenerateJumpFunction(object, a1, &miss); |
| 1551 | 1551 |
| 1552 HandlerFrontendFooter(&miss); | 1552 HandlerFrontendFooter(&miss); |
| 1553 | 1553 |
| 1554 // Return the generated code. | 1554 // Return the generated code. |
| 1555 return GetCode(Code::FAST, name); | 1555 return GetCode(Code::FAST, name); |
| 1556 } | 1556 } |
| 1557 | 1557 |
| 1558 | 1558 |
| 1559 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | |
| 1560 Handle<Object> object, | |
| 1561 Handle<JSObject> holder, | |
| 1562 Handle<Cell> cell, | |
| 1563 Handle<JSFunction> function, | |
| 1564 Handle<String> name, | |
| 1565 Code::StubType type) { | |
| 1566 Label miss; | |
| 1567 | |
| 1568 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 1569 if (!cell.is_null()) { | |
| 1570 ASSERT(cell->value() == *function); | |
| 1571 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 1572 } | |
| 1573 | |
| 1574 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | |
| 1575 site->SetElementsKind(GetInitialFastElementsKind()); | |
| 1576 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | |
| 1577 const int argc = arguments().immediate(); | |
| 1578 __ li(a0, Operand(argc)); | |
| 1579 __ li(a2, Operand(site_feedback_cell)); | |
| 1580 __ li(a1, Operand(function)); | |
| 1581 | |
| 1582 ArrayConstructorStub stub(isolate()); | |
| 1583 __ TailCallStub(&stub); | |
| 1584 | |
| 1585 HandlerFrontendFooter(&miss); | |
| 1586 | |
| 1587 // Return the generated code. | |
| 1588 return GetCode(type, name); | |
| 1589 } | |
| 1590 | |
| 1591 | |
| 1592 Handle<Code> CallStubCompiler::CompileArrayPushCall( | |
| 1593 Handle<Object> object, | |
| 1594 Handle<JSObject> holder, | |
| 1595 Handle<Cell> cell, | |
| 1596 Handle<JSFunction> function, | |
| 1597 Handle<String> name, | |
| 1598 Code::StubType type) { | |
| 1599 // If object is not an array or is observed or sealed, bail out to regular | |
| 1600 // call. | |
| 1601 if (!object->IsJSArray() || | |
| 1602 !cell.is_null() || | |
| 1603 Handle<JSArray>::cast(object)->map()->is_observed() || | |
| 1604 !Handle<JSArray>::cast(object)->map()->is_extensible()) { | |
| 1605 return Handle<Code>::null(); | |
| 1606 } | |
| 1607 | |
| 1608 Label miss; | |
| 1609 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 1610 Register receiver = a0; | |
| 1611 Register scratch = a1; | |
| 1612 | |
| 1613 const int argc = arguments().immediate(); | |
| 1614 | |
| 1615 if (argc == 0) { | |
| 1616 // Nothing to do, just return the length. | |
| 1617 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1618 __ DropAndRet(argc + 1); | |
| 1619 } else { | |
| 1620 Label call_builtin; | |
| 1621 if (argc == 1) { // Otherwise fall through to call the builtin. | |
| 1622 Label attempt_to_grow_elements, with_write_barrier, check_double; | |
| 1623 | |
| 1624 Register elements = t2; | |
| 1625 Register end_elements = t1; | |
| 1626 // Get the elements array of the object. | |
| 1627 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | |
| 1628 | |
| 1629 // Check that the elements are in fast mode and writable. | |
| 1630 __ CheckMap(elements, | |
| 1631 scratch, | |
| 1632 Heap::kFixedArrayMapRootIndex, | |
| 1633 &check_double, | |
| 1634 DONT_DO_SMI_CHECK); | |
| 1635 | |
| 1636 // Get the array's length into scratch and calculate new length. | |
| 1637 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1638 STATIC_ASSERT(kSmiTagSize == 1); | |
| 1639 STATIC_ASSERT(kSmiTag == 0); | |
| 1640 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); | |
| 1641 | |
| 1642 // Get the elements' length. | |
| 1643 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 1644 | |
| 1645 // Check if we could survive without allocation. | |
| 1646 __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0)); | |
| 1647 | |
| 1648 // Check if value is a smi. | |
| 1649 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 1650 __ JumpIfNotSmi(t0, &with_write_barrier); | |
| 1651 | |
| 1652 // Save new length. | |
| 1653 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1654 | |
| 1655 // Store the value. | |
| 1656 // We may need a register containing the address end_elements below, | |
| 1657 // so write back the value in end_elements. | |
| 1658 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); | |
| 1659 __ Addu(end_elements, elements, end_elements); | |
| 1660 const int kEndElementsOffset = | |
| 1661 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | |
| 1662 __ Addu(end_elements, end_elements, kEndElementsOffset); | |
| 1663 __ sw(t0, MemOperand(end_elements)); | |
| 1664 | |
| 1665 // Check for a smi. | |
| 1666 __ mov(v0, scratch); | |
| 1667 __ DropAndRet(argc + 1); | |
| 1668 | |
| 1669 __ bind(&check_double); | |
| 1670 | |
| 1671 // Check that the elements are in fast mode and writable. | |
| 1672 __ CheckMap(elements, | |
| 1673 scratch, | |
| 1674 Heap::kFixedDoubleArrayMapRootIndex, | |
| 1675 &call_builtin, | |
| 1676 DONT_DO_SMI_CHECK); | |
| 1677 | |
| 1678 // Get the array's length into scratch and calculate new length. | |
| 1679 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1680 STATIC_ASSERT(kSmiTagSize == 1); | |
| 1681 STATIC_ASSERT(kSmiTag == 0); | |
| 1682 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); | |
| 1683 | |
| 1684 // Get the elements' length. | |
| 1685 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 1686 | |
| 1687 // Check if we could survive without allocation. | |
| 1688 __ Branch(&call_builtin, gt, scratch, Operand(t0)); | |
| 1689 | |
| 1690 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 1691 __ StoreNumberToDoubleElements( | |
| 1692 t0, scratch, elements, a3, t1, a2, | |
| 1693 &call_builtin, argc * kDoubleSize); | |
| 1694 | |
| 1695 // Save new length. | |
| 1696 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1697 | |
| 1698 __ mov(v0, scratch); | |
| 1699 __ DropAndRet(argc + 1); | |
| 1700 | |
| 1701 __ bind(&with_write_barrier); | |
| 1702 | |
| 1703 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
| 1704 | |
| 1705 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | |
| 1706 Label fast_object, not_fast_object; | |
| 1707 __ CheckFastObjectElements(a3, t3, ¬_fast_object); | |
| 1708 __ jmp(&fast_object); | |
| 1709 // In case of fast smi-only, convert to fast object, otherwise bail out. | |
| 1710 __ bind(¬_fast_object); | |
| 1711 __ CheckFastSmiElements(a3, t3, &call_builtin); | |
| 1712 | |
| 1713 __ lw(t3, FieldMemOperand(t0, HeapObject::kMapOffset)); | |
| 1714 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | |
| 1715 __ Branch(&call_builtin, eq, t3, Operand(at)); | |
| 1716 // edx: receiver | |
| 1717 // a3: map | |
| 1718 Label try_holey_map; | |
| 1719 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
| 1720 FAST_ELEMENTS, | |
| 1721 a3, | |
| 1722 t3, | |
| 1723 &try_holey_map); | |
| 1724 __ mov(a2, receiver); | |
| 1725 ElementsTransitionGenerator:: | |
| 1726 GenerateMapChangeElementsTransition(masm(), | |
| 1727 DONT_TRACK_ALLOCATION_SITE, | |
| 1728 NULL); | |
| 1729 __ jmp(&fast_object); | |
| 1730 | |
| 1731 __ bind(&try_holey_map); | |
| 1732 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS, | |
| 1733 FAST_HOLEY_ELEMENTS, | |
| 1734 a3, | |
| 1735 t3, | |
| 1736 &call_builtin); | |
| 1737 __ mov(a2, receiver); | |
| 1738 ElementsTransitionGenerator:: | |
| 1739 GenerateMapChangeElementsTransition(masm(), | |
| 1740 DONT_TRACK_ALLOCATION_SITE, | |
| 1741 NULL); | |
| 1742 __ bind(&fast_object); | |
| 1743 } else { | |
| 1744 __ CheckFastObjectElements(a3, a3, &call_builtin); | |
| 1745 } | |
| 1746 | |
| 1747 // Save new length. | |
| 1748 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1749 | |
| 1750 // Store the value. | |
| 1751 // We may need a register containing the address end_elements below, | |
| 1752 // so write back the value in end_elements. | |
| 1753 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); | |
| 1754 __ Addu(end_elements, elements, end_elements); | |
| 1755 __ Addu(end_elements, end_elements, kEndElementsOffset); | |
| 1756 __ sw(t0, MemOperand(end_elements)); | |
| 1757 | |
| 1758 __ RecordWrite(elements, | |
| 1759 end_elements, | |
| 1760 t0, | |
| 1761 kRAHasNotBeenSaved, | |
| 1762 kDontSaveFPRegs, | |
| 1763 EMIT_REMEMBERED_SET, | |
| 1764 OMIT_SMI_CHECK); | |
| 1765 __ mov(v0, scratch); | |
| 1766 __ DropAndRet(argc + 1); | |
| 1767 | |
| 1768 __ bind(&attempt_to_grow_elements); | |
| 1769 // scratch: array's length + 1. | |
| 1770 // t0: elements' length. | |
| 1771 | |
| 1772 if (!FLAG_inline_new) { | |
| 1773 __ Branch(&call_builtin); | |
| 1774 } | |
| 1775 | |
| 1776 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 1777 // Growing elements that are SMI-only requires special handling in case | |
| 1778 // the new element is non-Smi. For now, delegate to the builtin. | |
| 1779 Label no_fast_elements_check; | |
| 1780 __ JumpIfSmi(a2, &no_fast_elements_check); | |
| 1781 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
| 1782 __ CheckFastObjectElements(t3, t3, &call_builtin); | |
| 1783 __ bind(&no_fast_elements_check); | |
| 1784 | |
| 1785 ExternalReference new_space_allocation_top = | |
| 1786 ExternalReference::new_space_allocation_top_address(isolate()); | |
| 1787 ExternalReference new_space_allocation_limit = | |
| 1788 ExternalReference::new_space_allocation_limit_address(isolate()); | |
| 1789 | |
| 1790 const int kAllocationDelta = 4; | |
| 1791 // Load top and check if it is the end of elements. | |
| 1792 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); | |
| 1793 __ Addu(end_elements, elements, end_elements); | |
| 1794 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); | |
| 1795 __ li(t3, Operand(new_space_allocation_top)); | |
| 1796 __ lw(a3, MemOperand(t3)); | |
| 1797 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); | |
| 1798 | |
| 1799 __ li(t5, Operand(new_space_allocation_limit)); | |
| 1800 __ lw(t5, MemOperand(t5)); | |
| 1801 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); | |
| 1802 __ Branch(&call_builtin, hi, a3, Operand(t5)); | |
| 1803 | |
| 1804 // We fit and could grow elements. | |
| 1805 // Update new_space_allocation_top. | |
| 1806 __ sw(a3, MemOperand(t3)); | |
| 1807 // Push the argument. | |
| 1808 __ sw(a2, MemOperand(end_elements)); | |
| 1809 // Fill the rest with holes. | |
| 1810 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); | |
| 1811 for (int i = 1; i < kAllocationDelta; i++) { | |
| 1812 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); | |
| 1813 } | |
| 1814 | |
| 1815 // Update elements' and array's sizes. | |
| 1816 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1817 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); | |
| 1818 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 1819 | |
| 1820 // Elements are in new space, so write barrier is not required. | |
| 1821 __ mov(v0, scratch); | |
| 1822 __ DropAndRet(argc + 1); | |
| 1823 } | |
| 1824 __ bind(&call_builtin); | |
| 1825 __ TailCallExternalReference( | |
| 1826 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | |
| 1827 } | |
| 1828 | |
| 1829 HandlerFrontendFooter(&miss); | |
| 1830 | |
| 1831 // Return the generated code. | |
| 1832 return GetCode(type, name); | |
| 1833 } | |
| 1834 | |
| 1835 | |
| 1836 Handle<Code> CallStubCompiler::CompileArrayPopCall( | |
| 1837 Handle<Object> object, | |
| 1838 Handle<JSObject> holder, | |
| 1839 Handle<Cell> cell, | |
| 1840 Handle<JSFunction> function, | |
| 1841 Handle<String> name, | |
| 1842 Code::StubType type) { | |
| 1843 // If object is not an array or is observed or sealed, bail out to regular | |
| 1844 // call. | |
| 1845 if (!object->IsJSArray() || | |
| 1846 !cell.is_null() || | |
| 1847 Handle<JSArray>::cast(object)->map()->is_observed() || | |
| 1848 !Handle<JSArray>::cast(object)->map()->is_extensible()) { | |
| 1849 return Handle<Code>::null(); | |
| 1850 } | |
| 1851 | |
| 1852 Label miss, return_undefined, call_builtin; | |
| 1853 Register receiver = a0; | |
| 1854 Register scratch = a1; | |
| 1855 Register elements = a3; | |
| 1856 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 1857 | |
| 1858 // Get the elements array of the object. | |
| 1859 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | |
| 1860 | |
| 1861 // Check that the elements are in fast mode and writable. | |
| 1862 __ CheckMap(elements, | |
| 1863 scratch, | |
| 1864 Heap::kFixedArrayMapRootIndex, | |
| 1865 &call_builtin, | |
| 1866 DONT_DO_SMI_CHECK); | |
| 1867 | |
| 1868 // Get the array's length into t0 and calculate new length. | |
| 1869 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1870 __ Subu(t0, t0, Operand(Smi::FromInt(1))); | |
| 1871 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); | |
| 1872 | |
| 1873 // Get the last element. | |
| 1874 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | |
| 1875 STATIC_ASSERT(kSmiTagSize == 1); | |
| 1876 STATIC_ASSERT(kSmiTag == 0); | |
| 1877 // We can't address the last element in one operation. Compute the more | |
| 1878 // expensive shift first, and use an offset later on. | |
| 1879 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); | |
| 1880 __ Addu(elements, elements, t1); | |
| 1881 __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize)); | |
| 1882 __ Branch(&call_builtin, eq, scratch, Operand(t2)); | |
| 1883 | |
| 1884 // Set the array's length. | |
| 1885 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 1886 | |
| 1887 // Fill with the hole. | |
| 1888 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); | |
| 1889 const int argc = arguments().immediate(); | |
| 1890 __ mov(v0, scratch); | |
| 1891 __ DropAndRet(argc + 1); | |
| 1892 | |
| 1893 __ bind(&return_undefined); | |
| 1894 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | |
| 1895 __ DropAndRet(argc + 1); | |
| 1896 | |
| 1897 __ bind(&call_builtin); | |
| 1898 __ TailCallExternalReference( | |
| 1899 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | |
| 1900 | |
| 1901 HandlerFrontendFooter(&miss); | |
| 1902 | |
| 1903 // Return the generated code. | |
| 1904 return GetCode(type, name); | |
| 1905 } | |
| 1906 | |
| 1907 | |
| 1908 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | |
| 1909 Handle<Object> object, | |
| 1910 Handle<JSObject> holder, | |
| 1911 Handle<Cell> cell, | |
| 1912 Handle<JSFunction> function, | |
| 1913 Handle<String> name, | |
| 1914 Code::StubType type) { | |
| 1915 // If object is not a string, bail out to regular call. | |
| 1916 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | |
| 1917 | |
| 1918 Label miss; | |
| 1919 Label name_miss; | |
| 1920 Label index_out_of_range; | |
| 1921 | |
| 1922 Label* index_out_of_range_label = &index_out_of_range; | |
| 1923 | |
| 1924 if (kind_ == Code::CALL_IC && | |
| 1925 (CallICBase::StringStubState::decode(extra_state()) == | |
| 1926 DEFAULT_STRING_STUB)) { | |
| 1927 index_out_of_range_label = &miss; | |
| 1928 } | |
| 1929 | |
| 1930 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | |
| 1931 | |
| 1932 Register receiver = a0; | |
| 1933 Register index = t1; | |
| 1934 Register result = a1; | |
| 1935 const int argc = arguments().immediate(); | |
| 1936 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1937 if (argc > 0) { | |
| 1938 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 1939 } else { | |
| 1940 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | |
| 1941 } | |
| 1942 | |
| 1943 StringCharCodeAtGenerator generator(receiver, | |
| 1944 index, | |
| 1945 result, | |
| 1946 &miss, // When not a string. | |
| 1947 &miss, // When not a number. | |
| 1948 index_out_of_range_label, | |
| 1949 STRING_INDEX_IS_NUMBER); | |
| 1950 generator.GenerateFast(masm()); | |
| 1951 __ mov(v0, result); | |
| 1952 __ DropAndRet(argc + 1); | |
| 1953 | |
| 1954 StubRuntimeCallHelper call_helper; | |
| 1955 generator.GenerateSlow(masm(), call_helper); | |
| 1956 | |
| 1957 if (index_out_of_range.is_linked()) { | |
| 1958 __ bind(&index_out_of_range); | |
| 1959 __ LoadRoot(v0, Heap::kNanValueRootIndex); | |
| 1960 __ DropAndRet(argc + 1); | |
| 1961 } | |
| 1962 | |
| 1963 __ bind(&miss); | |
| 1964 // Restore function name in a2. | |
| 1965 __ li(a2, name); | |
| 1966 HandlerFrontendFooter(&name_miss); | |
| 1967 | |
| 1968 // Return the generated code. | |
| 1969 return GetCode(type, name); | |
| 1970 } | |
| 1971 | |
| 1972 | |
| 1973 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | |
| 1974 Handle<Object> object, | |
| 1975 Handle<JSObject> holder, | |
| 1976 Handle<Cell> cell, | |
| 1977 Handle<JSFunction> function, | |
| 1978 Handle<String> name, | |
| 1979 Code::StubType type) { | |
| 1980 // If object is not a string, bail out to regular call. | |
| 1981 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | |
| 1982 | |
| 1983 const int argc = arguments().immediate(); | |
| 1984 Label miss; | |
| 1985 Label name_miss; | |
| 1986 Label index_out_of_range; | |
| 1987 Label* index_out_of_range_label = &index_out_of_range; | |
| 1988 if (kind_ == Code::CALL_IC && | |
| 1989 (CallICBase::StringStubState::decode(extra_state()) == | |
| 1990 DEFAULT_STRING_STUB)) { | |
| 1991 index_out_of_range_label = &miss; | |
| 1992 } | |
| 1993 | |
| 1994 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | |
| 1995 | |
| 1996 Register receiver = a0; | |
| 1997 Register index = t1; | |
| 1998 Register scratch = a3; | |
| 1999 Register result = a1; | |
| 2000 if (argc > 0) { | |
| 2001 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 2002 } else { | |
| 2003 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | |
| 2004 } | |
| 2005 | |
| 2006 StringCharAtGenerator generator(receiver, | |
| 2007 index, | |
| 2008 scratch, | |
| 2009 result, | |
| 2010 &miss, // When not a string. | |
| 2011 &miss, // When not a number. | |
| 2012 index_out_of_range_label, | |
| 2013 STRING_INDEX_IS_NUMBER); | |
| 2014 generator.GenerateFast(masm()); | |
| 2015 __ mov(v0, result); | |
| 2016 __ DropAndRet(argc + 1); | |
| 2017 | |
| 2018 StubRuntimeCallHelper call_helper; | |
| 2019 generator.GenerateSlow(masm(), call_helper); | |
| 2020 | |
| 2021 if (index_out_of_range.is_linked()) { | |
| 2022 __ bind(&index_out_of_range); | |
| 2023 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | |
| 2024 __ DropAndRet(argc + 1); | |
| 2025 } | |
| 2026 | |
| 2027 __ bind(&miss); | |
| 2028 // Restore function name in a2. | |
| 2029 __ li(a2, name); | |
| 2030 HandlerFrontendFooter(&name_miss); | |
| 2031 | |
| 2032 // Return the generated code. | |
| 2033 return GetCode(type, name); | |
| 2034 } | |
| 2035 | |
| 2036 | |
| 2037 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | |
| 2038 Handle<Object> object, | |
| 2039 Handle<JSObject> holder, | |
| 2040 Handle<Cell> cell, | |
| 2041 Handle<JSFunction> function, | |
| 2042 Handle<String> name, | |
| 2043 Code::StubType type) { | |
| 2044 const int argc = arguments().immediate(); | |
| 2045 | |
| 2046 // If the object is not a JSObject or we got an unexpected number of | |
| 2047 // arguments, bail out to the regular call. | |
| 2048 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | |
| 2049 | |
| 2050 Label miss; | |
| 2051 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2052 if (!cell.is_null()) { | |
| 2053 ASSERT(cell->value() == *function); | |
| 2054 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2055 } | |
| 2056 | |
| 2057 // Load the char code argument. | |
| 2058 Register code = a1; | |
| 2059 __ lw(code, MemOperand(sp, 0 * kPointerSize)); | |
| 2060 | |
| 2061 // Check the code is a smi. | |
| 2062 Label slow; | |
| 2063 STATIC_ASSERT(kSmiTag == 0); | |
| 2064 __ JumpIfNotSmi(code, &slow); | |
| 2065 | |
| 2066 // Convert the smi code to uint16. | |
| 2067 __ And(code, code, Operand(Smi::FromInt(0xffff))); | |
| 2068 | |
| 2069 StringCharFromCodeGenerator generator(code, v0); | |
| 2070 generator.GenerateFast(masm()); | |
| 2071 __ DropAndRet(argc + 1); | |
| 2072 | |
| 2073 StubRuntimeCallHelper call_helper; | |
| 2074 generator.GenerateSlow(masm(), call_helper); | |
| 2075 | |
| 2076 __ bind(&slow); | |
| 2077 // We do not have to patch the receiver because the function makes no use of | |
| 2078 // it. | |
| 2079 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2080 | |
| 2081 HandlerFrontendFooter(&miss); | |
| 2082 | |
| 2083 // Return the generated code. | |
| 2084 return GetCode(type, name); | |
| 2085 } | |
| 2086 | |
| 2087 | |
| 2088 Handle<Code> CallStubCompiler::CompileMathFloorCall( | |
| 2089 Handle<Object> object, | |
| 2090 Handle<JSObject> holder, | |
| 2091 Handle<Cell> cell, | |
| 2092 Handle<JSFunction> function, | |
| 2093 Handle<String> name, | |
| 2094 Code::StubType type) { | |
| 2095 const int argc = arguments().immediate(); | |
| 2096 // If the object is not a JSObject or we got an unexpected number of | |
| 2097 // arguments, bail out to the regular call. | |
| 2098 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | |
| 2099 | |
| 2100 Label miss, slow; | |
| 2101 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2102 if (!cell.is_null()) { | |
| 2103 ASSERT(cell->value() == *function); | |
| 2104 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2105 } | |
| 2106 | |
| 2107 // Load the (only) argument into v0. | |
| 2108 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | |
| 2109 | |
| 2110 // If the argument is a smi, just return. | |
| 2111 STATIC_ASSERT(kSmiTag == 0); | |
| 2112 __ SmiTst(v0, t0); | |
| 2113 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); | |
| 2114 | |
| 2115 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); | |
| 2116 | |
| 2117 Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return; | |
| 2118 | |
| 2119 // If fpu is enabled, we use the floor instruction. | |
| 2120 | |
| 2121 // Load the HeapNumber value. | |
| 2122 __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); | |
| 2123 | |
| 2124 // Backup FCSR. | |
| 2125 __ cfc1(a3, FCSR); | |
| 2126 // Clearing FCSR clears the exception mask with no side-effects. | |
| 2127 __ ctc1(zero_reg, FCSR); | |
| 2128 // Convert the argument to an integer. | |
| 2129 __ floor_w_d(f0, f0); | |
| 2130 | |
| 2131 // Start checking for special cases. | |
| 2132 // Get the argument exponent and clear the sign bit. | |
| 2133 __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize)); | |
| 2134 __ And(t2, t1, Operand(~HeapNumber::kSignMask)); | |
| 2135 __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord); | |
| 2136 | |
| 2137 // Retrieve FCSR and check for fpu errors. | |
| 2138 __ cfc1(t5, FCSR); | |
| 2139 __ And(t5, t5, Operand(kFCSRExceptionFlagMask)); | |
| 2140 __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg)); | |
| 2141 | |
| 2142 // Check for NaN, Infinity, and -Infinity. | |
| 2143 // They are invariant through a Math.Floor call, so just | |
| 2144 // return the original argument. | |
| 2145 __ Subu(t3, t2, Operand(HeapNumber::kExponentMask | |
| 2146 >> HeapNumber::kMantissaBitsInTopWord)); | |
| 2147 __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg)); | |
| 2148 // We had an overflow or underflow in the conversion. Check if we | |
| 2149 // have a big exponent. | |
| 2150 // If greater or equal, the argument is already round and in v0. | |
| 2151 __ Branch(&restore_fcsr_and_return, ge, t3, | |
| 2152 Operand(HeapNumber::kMantissaBits)); | |
| 2153 __ Branch(&wont_fit_smi); | |
| 2154 | |
| 2155 __ bind(&no_fpu_error); | |
| 2156 // Move the result back to v0. | |
| 2157 __ mfc1(v0, f0); | |
| 2158 // Check if the result fits into a smi. | |
| 2159 __ Addu(a1, v0, Operand(0x40000000)); | |
| 2160 __ Branch(&wont_fit_smi, lt, a1, Operand(zero_reg)); | |
| 2161 // Tag the result. | |
| 2162 STATIC_ASSERT(kSmiTag == 0); | |
| 2163 __ sll(v0, v0, kSmiTagSize); | |
| 2164 | |
| 2165 // Check for -0. | |
| 2166 __ Branch(&restore_fcsr_and_return, ne, v0, Operand(zero_reg)); | |
| 2167 // t1 already holds the HeapNumber exponent. | |
| 2168 __ And(t0, t1, Operand(HeapNumber::kSignMask)); | |
| 2169 // If our HeapNumber is negative it was -0, so load its address and return. | |
| 2170 // Else v0 is loaded with 0, so we can also just return. | |
| 2171 __ Branch(&restore_fcsr_and_return, eq, t0, Operand(zero_reg)); | |
| 2172 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | |
| 2173 | |
| 2174 __ bind(&restore_fcsr_and_return); | |
| 2175 // Restore FCSR and return. | |
| 2176 __ ctc1(a3, FCSR); | |
| 2177 | |
| 2178 __ DropAndRet(argc + 1); | |
| 2179 | |
| 2180 __ bind(&wont_fit_smi); | |
| 2181 // Restore FCSR and fall to slow case. | |
| 2182 __ ctc1(a3, FCSR); | |
| 2183 | |
| 2184 __ bind(&slow); | |
| 2185 // We do not have to patch the receiver because the function makes no use of | |
| 2186 // it. | |
| 2187 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2188 | |
| 2189 HandlerFrontendFooter(&miss); | |
| 2190 | |
| 2191 // Return the generated code. | |
| 2192 return GetCode(type, name); | |
| 2193 } | |
| 2194 | |
| 2195 | |
| 2196 Handle<Code> CallStubCompiler::CompileMathAbsCall( | |
| 2197 Handle<Object> object, | |
| 2198 Handle<JSObject> holder, | |
| 2199 Handle<Cell> cell, | |
| 2200 Handle<JSFunction> function, | |
| 2201 Handle<String> name, | |
| 2202 Code::StubType type) { | |
| 2203 const int argc = arguments().immediate(); | |
| 2204 // If the object is not a JSObject or we got an unexpected number of | |
| 2205 // arguments, bail out to the regular call. | |
| 2206 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | |
| 2207 | |
| 2208 Label miss; | |
| 2209 | |
| 2210 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2211 if (!cell.is_null()) { | |
| 2212 ASSERT(cell->value() == *function); | |
| 2213 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2214 } | |
| 2215 | |
| 2216 // Load the (only) argument into v0. | |
| 2217 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | |
| 2218 | |
| 2219 // Check if the argument is a smi. | |
| 2220 Label not_smi; | |
| 2221 STATIC_ASSERT(kSmiTag == 0); | |
| 2222 __ JumpIfNotSmi(v0, ¬_smi); | |
| 2223 | |
| 2224 // Do bitwise not or do nothing depending on the sign of the | |
| 2225 // argument. | |
| 2226 __ sra(t0, v0, kBitsPerInt - 1); | |
| 2227 __ Xor(a1, v0, t0); | |
| 2228 | |
| 2229 // Add 1 or do nothing depending on the sign of the argument. | |
| 2230 __ Subu(v0, a1, t0); | |
| 2231 | |
| 2232 // If the result is still negative, go to the slow case. | |
| 2233 // This only happens for the most negative smi. | |
| 2234 Label slow; | |
| 2235 __ Branch(&slow, lt, v0, Operand(zero_reg)); | |
| 2236 | |
| 2237 // Smi case done. | |
| 2238 __ DropAndRet(argc + 1); | |
| 2239 | |
| 2240 // Check if the argument is a heap number and load its exponent and | |
| 2241 // sign. | |
| 2242 __ bind(¬_smi); | |
| 2243 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); | |
| 2244 __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | |
| 2245 | |
| 2246 // Check the sign of the argument. If the argument is positive, | |
| 2247 // just return it. | |
| 2248 Label negative_sign; | |
| 2249 __ And(t0, a1, Operand(HeapNumber::kSignMask)); | |
| 2250 __ Branch(&negative_sign, ne, t0, Operand(zero_reg)); | |
| 2251 __ DropAndRet(argc + 1); | |
| 2252 | |
| 2253 // If the argument is negative, clear the sign, and return a new | |
| 2254 // number. | |
| 2255 __ bind(&negative_sign); | |
| 2256 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); | |
| 2257 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | |
| 2258 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); | |
| 2259 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); | |
| 2260 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | |
| 2261 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | |
| 2262 __ DropAndRet(argc + 1); | |
| 2263 | |
| 2264 __ bind(&slow); | |
| 2265 // We do not have to patch the receiver because the function makes no use of | |
| 2266 // it. | |
| 2267 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2268 | |
| 2269 HandlerFrontendFooter(&miss); | |
| 2270 | |
| 2271 // Return the generated code. | |
| 2272 return GetCode(type, name); | |
| 2273 } | |
| 2274 | |
| 2275 | |
| 2276 Handle<Code> CallStubCompiler::CompileFastApiCall( | 1559 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2277 const CallOptimization& optimization, | 1560 const CallOptimization& optimization, |
| 2278 Handle<Object> object, | 1561 Handle<Object> object, |
| 2279 Handle<JSObject> holder, | 1562 Handle<JSObject> holder, |
| 2280 Handle<Cell> cell, | 1563 Handle<Cell> cell, |
| 2281 Handle<JSFunction> function, | 1564 Handle<JSFunction> function, |
| 2282 Handle<String> name) { | 1565 Handle<String> name) { |
| 2283 | 1566 |
| 2284 Counters* counters = isolate()->counters(); | 1567 Counters* counters = isolate()->counters(); |
| 2285 | 1568 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 // Return the generated code. | 1790 // Return the generated code. |
| 2508 return GetCode(Code::NORMAL, name); | 1791 return GetCode(Code::NORMAL, name); |
| 2509 } | 1792 } |
| 2510 | 1793 |
| 2511 | 1794 |
| 2512 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1795 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2513 Handle<JSObject> object, | 1796 Handle<JSObject> object, |
| 2514 Handle<JSObject> holder, | 1797 Handle<JSObject> holder, |
| 2515 Handle<Name> name, | 1798 Handle<Name> name, |
| 2516 Handle<ExecutableAccessorInfo> callback) { | 1799 Handle<ExecutableAccessorInfo> callback) { |
| 2517 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), | 1800 Register holder_reg = HandlerFrontend( |
| 2518 receiver(), holder, name); | 1801 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 2519 | 1802 |
| 2520 // Stub never generated for non-global objects that require access | 1803 // Stub never generated for non-global objects that require access |
| 2521 // checks. | 1804 // checks. |
| 2522 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1805 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 2523 | 1806 |
| 2524 __ push(receiver()); // Receiver. | 1807 __ push(receiver()); // Receiver. |
| 1808 __ push(holder_reg); |
| 2525 __ li(at, Operand(callback)); // Callback info. | 1809 __ li(at, Operand(callback)); // Callback info. |
| 2526 __ push(at); | 1810 __ push(at); |
| 2527 __ li(at, Operand(name)); | 1811 __ li(at, Operand(name)); |
| 2528 __ Push(at, value()); | 1812 __ Push(at, value()); |
| 2529 | 1813 |
| 2530 // Do tail-call to the runtime system. | 1814 // Do tail-call to the runtime system. |
| 2531 ExternalReference store_callback_property = | 1815 ExternalReference store_callback_property = |
| 2532 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1816 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2533 __ TailCallExternalReference(store_callback_property, 4, 1); | 1817 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 2534 | 1818 |
| 2535 // Return the generated code. | 1819 // Return the generated code. |
| 2536 return GetCode(kind(), Code::FAST, name); | 1820 return GetCode(kind(), Code::FAST, name); |
| 2537 } | 1821 } |
| 2538 | 1822 |
| 2539 | 1823 |
| 2540 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1824 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2541 Handle<JSObject> object, | 1825 Handle<JSObject> object, |
| 2542 Handle<JSObject> holder, | 1826 Handle<JSObject> holder, |
| 2543 Handle<Name> name, | 1827 Handle<Name> name, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2628 | 1912 |
| 2629 // Handle store cache miss. | 1913 // Handle store cache miss. |
| 2630 __ bind(&miss); | 1914 __ bind(&miss); |
| 2631 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1915 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2632 | 1916 |
| 2633 // Return the generated code. | 1917 // Return the generated code. |
| 2634 return GetCode(kind(), Code::FAST, name); | 1918 return GetCode(kind(), Code::FAST, name); |
| 2635 } | 1919 } |
| 2636 | 1920 |
| 2637 | 1921 |
| 2638 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, | 1922 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, |
| 2639 Handle<JSObject> last, | 1923 Handle<JSObject> last, |
| 2640 Handle<Name> name) { | 1924 Handle<Name> name) { |
| 2641 NonexistentHandlerFrontend(type, last, name); | 1925 NonexistentHandlerFrontend(type, last, name); |
| 2642 | 1926 |
| 2643 // Return undefined if maps of the full prototype chain is still the same. | 1927 // Return undefined if maps of the full prototype chain is still the same. |
| 2644 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1928 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 2645 __ Ret(); | 1929 __ Ret(); |
| 2646 | 1930 |
| 2647 // Return the generated code. | 1931 // Return the generated code. |
| 2648 return GetCode(kind(), Code::FAST, name); | 1932 return GetCode(kind(), Code::FAST, name); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2670 } | 1954 } |
| 2671 | 1955 |
| 2672 | 1956 |
| 2673 Register* KeyedStoreStubCompiler::registers() { | 1957 Register* KeyedStoreStubCompiler::registers() { |
| 2674 // receiver, name, value, scratch1, scratch2, scratch3. | 1958 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2675 static Register registers[] = { a2, a1, a0, a3, t0, t1 }; | 1959 static Register registers[] = { a2, a1, a0, a3, t0, t1 }; |
| 2676 return registers; | 1960 return registers; |
| 2677 } | 1961 } |
| 2678 | 1962 |
| 2679 | 1963 |
| 2680 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, | |
| 2681 Register name_reg, | |
| 2682 Label* miss) { | |
| 2683 __ Branch(miss, ne, name_reg, Operand(name)); | |
| 2684 } | |
| 2685 | |
| 2686 | |
| 2687 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name, | |
| 2688 Register name_reg, | |
| 2689 Label* miss) { | |
| 2690 __ Branch(miss, ne, name_reg, Operand(name)); | |
| 2691 } | |
| 2692 | |
| 2693 | |
| 2694 #undef __ | 1964 #undef __ |
| 2695 #define __ ACCESS_MASM(masm) | 1965 #define __ ACCESS_MASM(masm) |
| 2696 | 1966 |
| 2697 | 1967 |
| 2698 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1968 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 2699 Register receiver, | 1969 Register receiver, |
| 2700 Handle<JSFunction> getter) { | 1970 Handle<JSFunction> getter) { |
| 2701 // ----------- S t a t e ------------- | 1971 // ----------- S t a t e ------------- |
| 2702 // -- a0 : receiver | 1972 // -- a0 : receiver |
| 2703 // -- a2 : name | 1973 // -- a2 : name |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2724 } | 1994 } |
| 2725 __ Ret(); | 1995 __ Ret(); |
| 2726 } | 1996 } |
| 2727 | 1997 |
| 2728 | 1998 |
| 2729 #undef __ | 1999 #undef __ |
| 2730 #define __ ACCESS_MASM(masm()) | 2000 #define __ ACCESS_MASM(masm()) |
| 2731 | 2001 |
| 2732 | 2002 |
| 2733 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2003 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2734 Handle<Type> type, | 2004 Handle<HeapType> type, |
| 2735 Handle<GlobalObject> global, | 2005 Handle<GlobalObject> global, |
| 2736 Handle<PropertyCell> cell, | 2006 Handle<PropertyCell> cell, |
| 2737 Handle<Name> name, | 2007 Handle<Name> name, |
| 2738 bool is_dont_delete) { | 2008 bool is_dont_delete) { |
| 2739 Label miss; | 2009 Label miss; |
| 2740 | 2010 |
| 2741 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 2011 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 2742 | 2012 |
| 2743 // Get the value from the cell. | 2013 // Get the value from the cell. |
| 2744 __ li(a3, Operand(cell)); | 2014 __ li(a3, Operand(cell)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2763 | 2033 |
| 2764 | 2034 |
| 2765 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 2035 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 2766 TypeHandleList* types, | 2036 TypeHandleList* types, |
| 2767 CodeHandleList* handlers, | 2037 CodeHandleList* handlers, |
| 2768 Handle<Name> name, | 2038 Handle<Name> name, |
| 2769 Code::StubType type, | 2039 Code::StubType type, |
| 2770 IcCheckType check) { | 2040 IcCheckType check) { |
| 2771 Label miss; | 2041 Label miss; |
| 2772 | 2042 |
| 2773 if (check == PROPERTY) { | 2043 if (check == PROPERTY && |
| 2774 GenerateNameCheck(name, this->name(), &miss); | 2044 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
| 2045 __ Branch(&miss, ne, this->name(), Operand(name)); |
| 2775 } | 2046 } |
| 2776 | 2047 |
| 2777 Label number_case; | 2048 Label number_case; |
| 2778 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 2049 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| 2779 __ JumpIfSmi(receiver(), smi_target); | 2050 __ JumpIfSmi(receiver(), smi_target); |
| 2780 | 2051 |
| 2781 Register map_reg = scratch1(); | 2052 Register map_reg = scratch1(); |
| 2782 | 2053 |
| 2783 int receiver_count = types->length(); | 2054 int receiver_count = types->length(); |
| 2784 int number_of_handled_maps = 0; | 2055 int number_of_handled_maps = 0; |
| 2785 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 2056 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
| 2786 for (int current = 0; current < receiver_count; ++current) { | 2057 for (int current = 0; current < receiver_count; ++current) { |
| 2787 Handle<Type> type = types->at(current); | 2058 Handle<HeapType> type = types->at(current); |
| 2788 Handle<Map> map = IC::TypeToMap(*type, isolate()); | 2059 Handle<Map> map = IC::TypeToMap(*type, isolate()); |
| 2789 if (!map->is_deprecated()) { | 2060 if (!map->is_deprecated()) { |
| 2790 number_of_handled_maps++; | 2061 number_of_handled_maps++; |
| 2791 if (type->Is(Type::Number())) { | 2062 if (type->Is(HeapType::Number())) { |
| 2792 ASSERT(!number_case.is_unused()); | 2063 ASSERT(!number_case.is_unused()); |
| 2793 __ bind(&number_case); | 2064 __ bind(&number_case); |
| 2794 } | 2065 } |
| 2795 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 2066 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |
| 2796 eq, map_reg, Operand(map)); | 2067 eq, map_reg, Operand(map)); |
| 2797 } | 2068 } |
| 2798 } | 2069 } |
| 2799 ASSERT(number_of_handled_maps != 0); | 2070 ASSERT(number_of_handled_maps != 0); |
| 2800 | 2071 |
| 2801 __ bind(&miss); | 2072 __ bind(&miss); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2884 // ----------------------------------- | 2155 // ----------------------------------- |
| 2885 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2156 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2886 } | 2157 } |
| 2887 | 2158 |
| 2888 | 2159 |
| 2889 #undef __ | 2160 #undef __ |
| 2890 | 2161 |
| 2891 } } // namespace v8::internal | 2162 } } // namespace v8::internal |
| 2892 | 2163 |
| 2893 #endif // V8_TARGET_ARCH_MIPS | 2164 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |