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 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1602 | 1602 |
| 1603 | 1603 |
| 1604 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1604 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1605 if (kind_ == Code::KEYED_CALL_IC) { | 1605 if (kind_ == Code::KEYED_CALL_IC) { |
| 1606 __ cmp(ecx, Immediate(name)); | 1606 __ cmp(ecx, Immediate(name)); |
| 1607 __ j(not_equal, miss); | 1607 __ j(not_equal, miss); |
| 1608 } | 1608 } |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 | 1611 |
| 1612 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | |
| 1613 Handle<JSObject> holder, | |
| 1614 Handle<Name> name, | |
| 1615 Label* miss) { | |
| 1616 ASSERT(holder->IsGlobalObject()); | |
| 1617 | |
| 1618 // Get the number of arguments. | |
| 1619 const int argc = arguments().immediate(); | |
| 1620 | |
| 1621 // Get the receiver from the stack. | |
| 1622 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1623 | |
| 1624 | |
| 1625 // Check that the maps haven't changed. | |
| 1626 __ JumpIfSmi(edx, miss); | |
| 1627 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 1628 ebx, eax, edi, name, miss); | |
| 1629 } | |
| 1630 | |
| 1631 | |
| 1632 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1612 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1633 Handle<Cell> cell, | 1613 Handle<Cell> cell, |
| 1634 Handle<JSFunction> function, | 1614 Handle<JSFunction> function, |
| 1635 Label* miss) { | 1615 Label* miss) { |
| 1636 // Get the value from the cell. | 1616 // Get the value from the cell. |
| 1637 if (Serializer::enabled()) { | 1617 if (Serializer::enabled()) { |
| 1638 __ mov(edi, Immediate(cell)); | 1618 __ mov(edi, Immediate(cell)); |
| 1639 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); | 1619 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); |
| 1640 } else { | 1620 } else { |
| 1641 __ mov(edi, Operand::ForCell(cell)); | 1621 __ mov(edi, Operand::ForCell(cell)); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1668 kind_, | 1648 kind_, |
| 1669 extra_state_); | 1649 extra_state_); |
| 1670 __ jmp(code, RelocInfo::CODE_TARGET); | 1650 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1671 } | 1651 } |
| 1672 | 1652 |
| 1673 | 1653 |
| 1674 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1654 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1675 Handle<JSObject> holder, | 1655 Handle<JSObject> holder, |
| 1676 PropertyIndex index, | 1656 PropertyIndex index, |
| 1677 Handle<Name> name) { | 1657 Handle<Name> name) { |
| 1678 // ----------- S t a t e ------------- | |
| 1679 // -- ecx : name | |
| 1680 // -- esp[0] : return address | |
| 1681 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 1682 // -- ... | |
| 1683 // -- esp[(argc + 1) * 4] : receiver | |
| 1684 // ----------------------------------- | |
| 1685 Label miss; | 1658 Label miss; |
| 1686 | 1659 |
| 1687 GenerateNameCheck(name, &miss); | 1660 Register reg = HandlerFrontendHeader( |
| 1688 | 1661 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1689 // Get the receiver from the stack. | |
| 1690 const int argc = arguments().immediate(); | |
| 1691 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1692 | |
| 1693 // Check that the receiver isn't a smi. | |
| 1694 __ JumpIfSmi(edx, &miss); | |
| 1695 | |
| 1696 // Do the right check and compute the holder register. | |
| 1697 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, | |
| 1698 holder, ebx, eax, edi, name, &miss); | |
| 1699 | 1662 |
| 1700 GenerateFastPropertyLoad( | 1663 GenerateFastPropertyLoad( |
| 1701 masm(), edi, reg, index.is_inobject(holder), | 1664 masm(), edi, reg, index.is_inobject(holder), |
| 1702 index.translate(holder), Representation::Tagged()); | 1665 index.translate(holder), Representation::Tagged()); |
| 1703 | 1666 |
| 1704 // Check that the function really is a function. | 1667 // Check that the function really is a function. |
| 1705 __ JumpIfSmi(edi, &miss); | 1668 __ JumpIfSmi(edi, &miss); |
| 1706 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1669 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1707 __ j(not_equal, &miss); | 1670 __ j(not_equal, &miss); |
| 1708 | 1671 |
| 1709 // Patch the receiver on the stack with the global proxy if | 1672 PatchGlobalProxy(object); |
| 1710 // necessary. | |
| 1711 if (object->IsGlobalObject()) { | |
| 1712 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | |
| 1713 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | |
| 1714 } | |
| 1715 | 1673 |
| 1716 // Invoke the function. | 1674 // Invoke the function. |
| 1717 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1675 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1718 ? CALL_AS_FUNCTION | 1676 ? CALL_AS_FUNCTION |
| 1719 : CALL_AS_METHOD; | 1677 : CALL_AS_METHOD; |
| 1720 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 1678 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 1721 NullCallWrapper(), call_kind); | 1679 NullCallWrapper(), call_kind); |
| 1722 | 1680 |
| 1723 // Handle call cache miss. | 1681 HandlerFrontendFooter(&miss); |
| 1724 __ bind(&miss); | |
| 1725 GenerateMissBranch(); | |
| 1726 | 1682 |
| 1727 // Return the generated code. | 1683 // Return the generated code. |
| 1728 return GetCode(Code::FAST, name); | 1684 return GetCode(Code::FAST, name); |
| 1729 } | 1685 } |
| 1730 | 1686 |
| 1731 | 1687 |
| 1732 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1688 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1733 Handle<Object> object, | 1689 Handle<Object> object, |
| 1734 Handle<JSObject> holder, | 1690 Handle<JSObject> holder, |
| 1735 Handle<Cell> cell, | 1691 Handle<Cell> cell, |
| 1736 Handle<JSFunction> function, | 1692 Handle<JSFunction> function, |
| 1737 Handle<String> name, | 1693 Handle<String> name, |
| 1738 Code::StubType type) { | 1694 Code::StubType type) { |
| 1739 Label miss; | 1695 Label miss; |
| 1740 | 1696 |
| 1741 // Check that function is still array | 1697 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1742 const int argc = arguments().immediate(); | 1698 if (!cell.is_null()) { |
| 1743 GenerateNameCheck(name, &miss); | |
| 1744 | |
| 1745 if (cell.is_null()) { | |
| 1746 // Get the receiver from the stack. | |
| 1747 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1748 | |
| 1749 // Check that the receiver isn't a smi. | |
| 1750 __ JumpIfSmi(edx, &miss); | |
| 1751 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 1752 ebx, eax, edi, name, &miss); | |
| 1753 } else { | |
| 1754 ASSERT(cell->value() == *function); | 1699 ASSERT(cell->value() == *function); |
| 1755 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1756 &miss); | |
| 1757 GenerateLoadFunctionFromCell(cell, function, &miss); | 1700 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1758 } | 1701 } |
| 1759 | 1702 |
| 1760 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1703 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1761 site->SetElementsKind(GetInitialFastElementsKind()); | 1704 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1762 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1705 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1706 const int argc = arguments().immediate(); | |
| 1763 __ mov(eax, Immediate(argc)); | 1707 __ mov(eax, Immediate(argc)); |
| 1764 __ mov(ebx, site_feedback_cell); | 1708 __ mov(ebx, site_feedback_cell); |
| 1765 __ mov(edi, function); | 1709 __ mov(edi, function); |
| 1766 | 1710 |
| 1767 ArrayConstructorStub stub(isolate()); | 1711 ArrayConstructorStub stub(isolate()); |
| 1768 __ TailCallStub(&stub); | 1712 __ TailCallStub(&stub); |
| 1769 | 1713 |
| 1770 __ bind(&miss); | 1714 HandlerFrontendFooter(&miss); |
| 1771 GenerateMissBranch(); | |
| 1772 | 1715 |
| 1773 // Return the generated code. | 1716 // Return the generated code. |
| 1774 return GetCode(type, name); | 1717 return GetCode(type, name); |
| 1775 } | 1718 } |
| 1776 | 1719 |
| 1777 | 1720 |
| 1778 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1721 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1779 Handle<Object> object, | 1722 Handle<Object> object, |
| 1780 Handle<JSObject> holder, | 1723 Handle<JSObject> holder, |
| 1781 Handle<Cell> cell, | 1724 Handle<Cell> cell, |
| 1782 Handle<JSFunction> function, | 1725 Handle<JSFunction> function, |
| 1783 Handle<String> name, | 1726 Handle<String> name, |
| 1784 Code::StubType type) { | 1727 Code::StubType type) { |
| 1785 // ----------- S t a t e ------------- | |
| 1786 // -- ecx : name | |
| 1787 // -- esp[0] : return address | |
| 1788 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 1789 // -- ... | |
| 1790 // -- esp[(argc + 1) * 4] : receiver | |
| 1791 // ----------------------------------- | |
| 1792 | |
| 1793 // If object is not an array or is observed, bail out to regular call. | 1728 // If object is not an array or is observed, bail out to regular call. |
| 1794 if (!object->IsJSArray() || | 1729 if (!object->IsJSArray() || |
| 1795 !cell.is_null() || | 1730 !cell.is_null() || |
| 1796 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1731 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1797 return Handle<Code>::null(); | 1732 return Handle<Code>::null(); |
| 1798 } | 1733 } |
| 1799 | 1734 |
| 1800 Label miss; | 1735 Label miss; |
| 1801 | 1736 |
| 1802 GenerateNameCheck(name, &miss); | 1737 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1803 | 1738 |
| 1804 // Get the receiver from the stack. | |
| 1805 const int argc = arguments().immediate(); | 1739 const int argc = arguments().immediate(); |
| 1806 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1807 | |
| 1808 // Check that the receiver isn't a smi. | |
| 1809 __ JumpIfSmi(edx, &miss); | |
| 1810 | |
| 1811 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 1812 ebx, eax, edi, name, &miss); | |
| 1813 | |
| 1814 if (argc == 0) { | 1740 if (argc == 0) { |
| 1815 // Noop, return the length. | 1741 // Noop, return the length. |
| 1816 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1742 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1817 __ ret((argc + 1) * kPointerSize); | 1743 __ ret((argc + 1) * kPointerSize); |
| 1818 } else { | 1744 } else { |
| 1819 Label call_builtin; | 1745 Label call_builtin; |
| 1820 | 1746 |
| 1821 if (argc == 1) { // Otherwise fall through to call builtin. | 1747 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1822 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1748 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1823 | 1749 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2021 __ ret((argc + 1) * kPointerSize); | 1947 __ ret((argc + 1) * kPointerSize); |
| 2022 } | 1948 } |
| 2023 | 1949 |
| 2024 __ bind(&call_builtin); | 1950 __ bind(&call_builtin); |
| 2025 __ TailCallExternalReference( | 1951 __ TailCallExternalReference( |
| 2026 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1952 ExternalReference(Builtins::c_ArrayPush, isolate()), |
| 2027 argc + 1, | 1953 argc + 1, |
| 2028 1); | 1954 1); |
| 2029 } | 1955 } |
| 2030 | 1956 |
| 2031 __ bind(&miss); | 1957 HandlerFrontendFooter(&miss); |
| 2032 GenerateMissBranch(); | |
| 2033 | 1958 |
| 2034 // Return the generated code. | 1959 // Return the generated code. |
| 2035 return GetCode(type, name); | 1960 return GetCode(type, name); |
| 2036 } | 1961 } |
| 2037 | 1962 |
| 2038 | 1963 |
| 2039 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1964 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 2040 Handle<Object> object, | 1965 Handle<Object> object, |
| 2041 Handle<JSObject> holder, | 1966 Handle<JSObject> holder, |
| 2042 Handle<Cell> cell, | 1967 Handle<Cell> cell, |
| 2043 Handle<JSFunction> function, | 1968 Handle<JSFunction> function, |
| 2044 Handle<String> name, | 1969 Handle<String> name, |
| 2045 Code::StubType type) { | 1970 Code::StubType type) { |
| 2046 // ----------- S t a t e ------------- | |
| 2047 // -- ecx : name | |
| 2048 // -- esp[0] : return address | |
| 2049 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2050 // -- ... | |
| 2051 // -- esp[(argc + 1) * 4] : receiver | |
| 2052 // ----------------------------------- | |
| 2053 | |
| 2054 // If object is not an array or is observed, bail out to regular call. | 1971 // If object is not an array or is observed, bail out to regular call. |
| 2055 if (!object->IsJSArray() || | 1972 if (!object->IsJSArray() || |
| 2056 !cell.is_null() || | 1973 !cell.is_null() || |
| 2057 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1974 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 2058 return Handle<Code>::null(); | 1975 return Handle<Code>::null(); |
| 2059 } | 1976 } |
| 2060 | 1977 |
| 2061 Label miss, return_undefined, call_builtin; | 1978 Label miss, return_undefined, call_builtin; |
| 2062 | 1979 |
| 2063 GenerateNameCheck(name, &miss); | 1980 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2064 | |
| 2065 // Get the receiver from the stack. | |
| 2066 const int argc = arguments().immediate(); | |
| 2067 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 2068 | |
| 2069 // Check that the receiver isn't a smi. | |
| 2070 __ JumpIfSmi(edx, &miss); | |
| 2071 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 2072 ebx, eax, edi, name, &miss); | |
| 2073 | 1981 |
| 2074 // Get the elements array of the object. | 1982 // Get the elements array of the object. |
| 2075 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1983 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 2076 | 1984 |
| 2077 // Check that the elements are in fast mode and writable. | 1985 // Check that the elements are in fast mode and writable. |
| 2078 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1986 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 2079 Immediate(factory()->fixed_array_map())); | 1987 Immediate(factory()->fixed_array_map())); |
| 2080 __ j(not_equal, &call_builtin); | 1988 __ j(not_equal, &call_builtin); |
| 2081 | 1989 |
| 2082 // Get the array's length into ecx and calculate new length. | 1990 // Get the array's length into ecx and calculate new length. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2094 __ j(equal, &call_builtin); | 2002 __ j(equal, &call_builtin); |
| 2095 | 2003 |
| 2096 // Set the array's length. | 2004 // Set the array's length. |
| 2097 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); | 2005 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); |
| 2098 | 2006 |
| 2099 // Fill with the hole. | 2007 // Fill with the hole. |
| 2100 __ mov(FieldOperand(ebx, | 2008 __ mov(FieldOperand(ebx, |
| 2101 ecx, times_half_pointer_size, | 2009 ecx, times_half_pointer_size, |
| 2102 FixedArray::kHeaderSize), | 2010 FixedArray::kHeaderSize), |
| 2103 Immediate(factory()->the_hole_value())); | 2011 Immediate(factory()->the_hole_value())); |
| 2012 const int argc = arguments().immediate(); | |
| 2104 __ ret((argc + 1) * kPointerSize); | 2013 __ ret((argc + 1) * kPointerSize); |
| 2105 | 2014 |
| 2106 __ bind(&return_undefined); | 2015 __ bind(&return_undefined); |
| 2107 __ mov(eax, Immediate(factory()->undefined_value())); | 2016 __ mov(eax, Immediate(factory()->undefined_value())); |
| 2108 __ ret((argc + 1) * kPointerSize); | 2017 __ ret((argc + 1) * kPointerSize); |
| 2109 | 2018 |
| 2110 __ bind(&call_builtin); | 2019 __ bind(&call_builtin); |
| 2111 __ TailCallExternalReference( | 2020 __ TailCallExternalReference( |
| 2112 ExternalReference(Builtins::c_ArrayPop, isolate()), | 2021 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 2113 argc + 1, | 2022 argc + 1, |
| 2114 1); | 2023 1); |
| 2115 | 2024 |
| 2116 __ bind(&miss); | 2025 HandlerFrontendFooter(&miss); |
| 2117 GenerateMissBranch(); | |
| 2118 | 2026 |
| 2119 // Return the generated code. | 2027 // Return the generated code. |
| 2120 return GetCode(type, name); | 2028 return GetCode(type, name); |
| 2121 } | 2029 } |
| 2122 | 2030 |
| 2123 | 2031 |
| 2124 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 2032 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2125 Handle<Object> object, | 2033 Handle<Object> object, |
| 2126 Handle<JSObject> holder, | 2034 Handle<JSObject> holder, |
| 2127 Handle<Cell> cell, | 2035 Handle<Cell> cell, |
| 2128 Handle<JSFunction> function, | 2036 Handle<JSFunction> function, |
| 2129 Handle<String> name, | 2037 Handle<String> name, |
| 2130 Code::StubType type) { | 2038 Code::StubType type) { |
| 2131 // ----------- S t a t e ------------- | |
| 2132 // -- ecx : function name | |
| 2133 // -- esp[0] : return address | |
| 2134 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2135 // -- ... | |
| 2136 // -- esp[(argc + 1) * 4] : receiver | |
| 2137 // ----------------------------------- | |
| 2138 | |
| 2139 // If object is not a string, bail out to regular call. | 2039 // If object is not a string, bail out to regular call. |
| 2140 if (!object->IsString() || !cell.is_null()) { | 2040 if (!object->IsString() || !cell.is_null()) { |
| 2141 return Handle<Code>::null(); | 2041 return Handle<Code>::null(); |
| 2142 } | 2042 } |
| 2143 | 2043 |
| 2144 const int argc = arguments().immediate(); | 2044 const int argc = arguments().immediate(); |
| 2145 | 2045 |
| 2146 Label miss; | 2046 Label miss; |
| 2147 Label name_miss; | 2047 Label name_miss; |
| 2148 Label index_out_of_range; | 2048 Label index_out_of_range; |
| 2149 Label* index_out_of_range_label = &index_out_of_range; | 2049 Label* index_out_of_range_label = &index_out_of_range; |
| 2150 | 2050 |
| 2151 if (kind_ == Code::CALL_IC && | 2051 if (kind_ == Code::CALL_IC && |
| 2152 (CallICBase::StringStubState::decode(extra_state_) == | 2052 (CallICBase::StringStubState::decode(extra_state_) == |
| 2153 DEFAULT_STRING_STUB)) { | 2053 DEFAULT_STRING_STUB)) { |
| 2154 index_out_of_range_label = &miss; | 2054 index_out_of_range_label = &miss; |
| 2155 } | 2055 } |
| 2156 | 2056 |
| 2157 GenerateNameCheck(name, &name_miss); | 2057 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2158 | |
| 2159 // Check that the maps starting from the prototype haven't changed. | |
| 2160 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2161 Context::STRING_FUNCTION_INDEX, | |
| 2162 eax, | |
| 2163 &miss); | |
| 2164 ASSERT(!object.is_identical_to(holder)); | |
| 2165 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2166 CheckPrototypes( | |
| 2167 IC::CurrentTypeOf(prototype, isolate()), | |
| 2168 eax, holder, ebx, edx, edi, name, &miss); | |
| 2169 | 2058 |
| 2170 Register receiver = ebx; | 2059 Register receiver = ebx; |
| 2171 Register index = edi; | 2060 Register index = edi; |
| 2172 Register result = eax; | 2061 Register result = eax; |
| 2173 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2062 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2174 if (argc > 0) { | 2063 if (argc > 0) { |
| 2175 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2064 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2176 } else { | 2065 } else { |
| 2177 __ Set(index, Immediate(factory()->undefined_value())); | 2066 __ Set(index, Immediate(factory()->undefined_value())); |
| 2178 } | 2067 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2207 } | 2096 } |
| 2208 | 2097 |
| 2209 | 2098 |
| 2210 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2099 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2211 Handle<Object> object, | 2100 Handle<Object> object, |
| 2212 Handle<JSObject> holder, | 2101 Handle<JSObject> holder, |
| 2213 Handle<Cell> cell, | 2102 Handle<Cell> cell, |
| 2214 Handle<JSFunction> function, | 2103 Handle<JSFunction> function, |
| 2215 Handle<String> name, | 2104 Handle<String> name, |
| 2216 Code::StubType type) { | 2105 Code::StubType type) { |
| 2217 // ----------- S t a t e ------------- | |
| 2218 // -- ecx : function name | |
| 2219 // -- esp[0] : return address | |
| 2220 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2221 // -- ... | |
| 2222 // -- esp[(argc + 1) * 4] : receiver | |
| 2223 // ----------------------------------- | |
| 2224 | |
| 2225 // If object is not a string, bail out to regular call. | 2106 // If object is not a string, bail out to regular call. |
| 2226 if (!object->IsString() || !cell.is_null()) { | 2107 if (!object->IsString() || !cell.is_null()) { |
| 2227 return Handle<Code>::null(); | 2108 return Handle<Code>::null(); |
| 2228 } | 2109 } |
| 2229 | 2110 |
| 2230 const int argc = arguments().immediate(); | 2111 const int argc = arguments().immediate(); |
| 2231 | 2112 |
| 2232 Label miss; | 2113 Label miss; |
| 2233 Label name_miss; | 2114 Label name_miss; |
| 2234 Label index_out_of_range; | 2115 Label index_out_of_range; |
| 2235 Label* index_out_of_range_label = &index_out_of_range; | 2116 Label* index_out_of_range_label = &index_out_of_range; |
| 2236 | 2117 |
| 2237 if (kind_ == Code::CALL_IC && | 2118 if (kind_ == Code::CALL_IC && |
| 2238 (CallICBase::StringStubState::decode(extra_state_) == | 2119 (CallICBase::StringStubState::decode(extra_state_) == |
| 2239 DEFAULT_STRING_STUB)) { | 2120 DEFAULT_STRING_STUB)) { |
| 2240 index_out_of_range_label = &miss; | 2121 index_out_of_range_label = &miss; |
| 2241 } | 2122 } |
| 2242 | 2123 |
| 2243 GenerateNameCheck(name, &name_miss); | 2124 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2244 | |
| 2245 // Check that the maps starting from the prototype haven't changed. | |
| 2246 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2247 Context::STRING_FUNCTION_INDEX, | |
| 2248 eax, | |
| 2249 &miss); | |
| 2250 ASSERT(!object.is_identical_to(holder)); | |
| 2251 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2252 CheckPrototypes( | |
| 2253 IC::CurrentTypeOf(prototype, isolate()), | |
| 2254 eax, holder, ebx, edx, edi, name, &miss); | |
| 2255 | 2125 |
| 2256 Register receiver = eax; | 2126 Register receiver = eax; |
| 2257 Register index = edi; | 2127 Register index = edi; |
| 2258 Register scratch = edx; | 2128 Register scratch = edx; |
| 2259 Register result = eax; | 2129 Register result = eax; |
| 2260 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2130 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2261 if (argc > 0) { | 2131 if (argc > 0) { |
| 2262 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2132 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2263 } else { | 2133 } else { |
| 2264 __ Set(index, Immediate(factory()->undefined_value())); | 2134 __ Set(index, Immediate(factory()->undefined_value())); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2295 } | 2165 } |
| 2296 | 2166 |
| 2297 | 2167 |
| 2298 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2168 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2299 Handle<Object> object, | 2169 Handle<Object> object, |
| 2300 Handle<JSObject> holder, | 2170 Handle<JSObject> holder, |
| 2301 Handle<Cell> cell, | 2171 Handle<Cell> cell, |
| 2302 Handle<JSFunction> function, | 2172 Handle<JSFunction> function, |
| 2303 Handle<String> name, | 2173 Handle<String> name, |
| 2304 Code::StubType type) { | 2174 Code::StubType type) { |
| 2305 // ----------- S t a t e ------------- | |
| 2306 // -- ecx : function name | |
| 2307 // -- esp[0] : return address | |
| 2308 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2309 // -- ... | |
| 2310 // -- esp[(argc + 1) * 4] : receiver | |
| 2311 // ----------------------------------- | |
| 2312 | |
| 2313 const int argc = arguments().immediate(); | 2175 const int argc = arguments().immediate(); |
| 2314 | 2176 |
| 2315 // If the object is not a JSObject or we got an unexpected number of | 2177 // If the object is not a JSObject or we got an unexpected number of |
| 2316 // arguments, bail out to the regular call. | 2178 // arguments, bail out to the regular call. |
| 2317 if (!object->IsJSObject() || argc != 1) { | 2179 if (!object->IsJSObject() || argc != 1) { |
| 2318 return Handle<Code>::null(); | 2180 return Handle<Code>::null(); |
| 2319 } | 2181 } |
| 2320 | 2182 |
| 2321 Label miss; | 2183 Label miss; |
| 2322 GenerateNameCheck(name, &miss); | |
| 2323 | 2184 |
| 2324 if (cell.is_null()) { | 2185 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2325 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2186 if (!cell.is_null()) { |
| 2326 STATIC_ASSERT(kSmiTag == 0); | |
| 2327 __ JumpIfSmi(edx, &miss); | |
| 2328 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 2329 ebx, eax, edi, name, &miss); | |
| 2330 } else { | |
| 2331 ASSERT(cell->value() == *function); | 2187 ASSERT(cell->value() == *function); |
| 2332 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2333 &miss); | |
| 2334 GenerateLoadFunctionFromCell(cell, function, &miss); | 2188 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2335 } | 2189 } |
| 2336 | 2190 |
| 2337 // Load the char code argument. | 2191 // Load the char code argument. |
| 2338 Register code = ebx; | 2192 Register code = ebx; |
| 2339 __ mov(code, Operand(esp, 1 * kPointerSize)); | 2193 __ mov(code, Operand(esp, 1 * kPointerSize)); |
| 2340 | 2194 |
| 2341 // Check the code is a smi. | 2195 // Check the code is a smi. |
| 2342 Label slow; | 2196 Label slow; |
| 2343 STATIC_ASSERT(kSmiTag == 0); | 2197 STATIC_ASSERT(kSmiTag == 0); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2356 // Tail call the full function. We do not have to patch the receiver | 2210 // Tail call the full function. We do not have to patch the receiver |
| 2357 // because the function makes no use of it. | 2211 // because the function makes no use of it. |
| 2358 __ bind(&slow); | 2212 __ bind(&slow); |
| 2359 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2213 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2360 ? CALL_AS_FUNCTION | 2214 ? CALL_AS_FUNCTION |
| 2361 : CALL_AS_METHOD; | 2215 : CALL_AS_METHOD; |
| 2362 ParameterCount expected(function); | 2216 ParameterCount expected(function); |
| 2363 __ InvokeFunction(function, expected, arguments(), | 2217 __ InvokeFunction(function, expected, arguments(), |
| 2364 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2218 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2365 | 2219 |
| 2366 __ bind(&miss); | 2220 HandlerFrontendFooter(&miss); |
| 2367 // ecx: function name. | |
| 2368 GenerateMissBranch(); | |
| 2369 | 2221 |
| 2370 // Return the generated code. | 2222 // Return the generated code. |
| 2371 return GetCode(type, name); | 2223 return GetCode(type, name); |
| 2372 } | 2224 } |
| 2373 | 2225 |
| 2374 | 2226 |
| 2375 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2227 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2376 Handle<Object> object, | 2228 Handle<Object> object, |
| 2377 Handle<JSObject> holder, | 2229 Handle<JSObject> holder, |
| 2378 Handle<Cell> cell, | 2230 Handle<Cell> cell, |
| 2379 Handle<JSFunction> function, | 2231 Handle<JSFunction> function, |
| 2380 Handle<String> name, | 2232 Handle<String> name, |
| 2381 Code::StubType type) { | 2233 Code::StubType type) { |
| 2382 // ----------- S t a t e ------------- | |
| 2383 // -- ecx : name | |
| 2384 // -- esp[0] : return address | |
| 2385 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2386 // -- ... | |
| 2387 // -- esp[(argc + 1) * 4] : receiver | |
| 2388 // ----------------------------------- | |
| 2389 | |
| 2390 if (!CpuFeatures::IsSupported(SSE2)) { | 2234 if (!CpuFeatures::IsSupported(SSE2)) { |
| 2391 return Handle<Code>::null(); | 2235 return Handle<Code>::null(); |
| 2392 } | 2236 } |
| 2393 | 2237 |
| 2394 CpuFeatureScope use_sse2(masm(), SSE2); | 2238 CpuFeatureScope use_sse2(masm(), SSE2); |
| 2395 | 2239 |
| 2396 const int argc = arguments().immediate(); | 2240 const int argc = arguments().immediate(); |
| 2397 | 2241 |
| 2398 // If the object is not a JSObject or we got an unexpected number of | 2242 // If the object is not a JSObject or we got an unexpected number of |
| 2399 // arguments, bail out to the regular call. | 2243 // arguments, bail out to the regular call. |
| 2400 if (!object->IsJSObject() || argc != 1) { | 2244 if (!object->IsJSObject() || argc != 1) { |
| 2401 return Handle<Code>::null(); | 2245 return Handle<Code>::null(); |
| 2402 } | 2246 } |
| 2403 | 2247 |
| 2404 Label miss; | 2248 Label miss; |
| 2405 GenerateNameCheck(name, &miss); | |
| 2406 | 2249 |
| 2407 if (cell.is_null()) { | 2250 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2408 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2251 if (!cell.is_null()) { |
| 2409 | |
| 2410 STATIC_ASSERT(kSmiTag == 0); | |
| 2411 __ JumpIfSmi(edx, &miss); | |
| 2412 | |
| 2413 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 2414 ebx, eax, edi, name, &miss); | |
| 2415 } else { | |
| 2416 ASSERT(cell->value() == *function); | 2252 ASSERT(cell->value() == *function); |
| 2417 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2418 &miss); | |
| 2419 GenerateLoadFunctionFromCell(cell, function, &miss); | 2253 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2420 } | 2254 } |
| 2421 | 2255 |
| 2422 // Load the (only) argument into eax. | 2256 // Load the (only) argument into eax. |
| 2423 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2257 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2424 | 2258 |
| 2425 // Check if the argument is a smi. | 2259 // Check if the argument is a smi. |
| 2426 Label smi; | 2260 Label smi; |
| 2427 STATIC_ASSERT(kSmiTag == 0); | 2261 STATIC_ASSERT(kSmiTag == 0); |
| 2428 __ JumpIfSmi(eax, &smi); | 2262 __ JumpIfSmi(eax, &smi); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2488 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2322 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2489 __ ret(2 * kPointerSize); | 2323 __ ret(2 * kPointerSize); |
| 2490 | 2324 |
| 2491 // Tail call the full function. We do not have to patch the receiver | 2325 // Tail call the full function. We do not have to patch the receiver |
| 2492 // because the function makes no use of it. | 2326 // because the function makes no use of it. |
| 2493 __ bind(&slow); | 2327 __ bind(&slow); |
| 2494 ParameterCount expected(function); | 2328 ParameterCount expected(function); |
| 2495 __ InvokeFunction(function, expected, arguments(), | 2329 __ InvokeFunction(function, expected, arguments(), |
| 2496 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2330 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2497 | 2331 |
| 2498 __ bind(&miss); | 2332 HandlerFrontendFooter(&miss); |
| 2499 // ecx: function name. | |
| 2500 GenerateMissBranch(); | |
| 2501 | 2333 |
| 2502 // Return the generated code. | 2334 // Return the generated code. |
| 2503 return GetCode(type, name); | 2335 return GetCode(type, name); |
| 2504 } | 2336 } |
| 2505 | 2337 |
| 2506 | 2338 |
| 2507 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2339 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2508 Handle<Object> object, | 2340 Handle<Object> object, |
| 2509 Handle<JSObject> holder, | 2341 Handle<JSObject> holder, |
| 2510 Handle<Cell> cell, | 2342 Handle<Cell> cell, |
| 2511 Handle<JSFunction> function, | 2343 Handle<JSFunction> function, |
| 2512 Handle<String> name, | 2344 Handle<String> name, |
| 2513 Code::StubType type) { | 2345 Code::StubType type) { |
| 2514 // ----------- S t a t e ------------- | |
| 2515 // -- ecx : name | |
| 2516 // -- esp[0] : return address | |
| 2517 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2518 // -- ... | |
| 2519 // -- esp[(argc + 1) * 4] : receiver | |
| 2520 // ----------------------------------- | |
| 2521 | |
| 2522 const int argc = arguments().immediate(); | 2346 const int argc = arguments().immediate(); |
| 2523 | 2347 |
| 2524 // If the object is not a JSObject or we got an unexpected number of | 2348 // If the object is not a JSObject or we got an unexpected number of |
| 2525 // arguments, bail out to the regular call. | 2349 // arguments, bail out to the regular call. |
| 2526 if (!object->IsJSObject() || argc != 1) { | 2350 if (!object->IsJSObject() || argc != 1) { |
| 2527 return Handle<Code>::null(); | 2351 return Handle<Code>::null(); |
| 2528 } | 2352 } |
| 2529 | 2353 |
| 2530 Label miss; | 2354 Label miss; |
| 2531 GenerateNameCheck(name, &miss); | |
| 2532 | 2355 |
| 2533 if (cell.is_null()) { | 2356 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2534 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2357 if (!cell.is_null()) { |
| 2535 | |
| 2536 STATIC_ASSERT(kSmiTag == 0); | |
| 2537 __ JumpIfSmi(edx, &miss); | |
| 2538 | |
| 2539 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | |
| 2540 ebx, eax, edi, name, &miss); | |
| 2541 } else { | |
| 2542 ASSERT(cell->value() == *function); | 2358 ASSERT(cell->value() == *function); |
| 2543 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2544 &miss); | |
| 2545 GenerateLoadFunctionFromCell(cell, function, &miss); | 2359 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2546 } | 2360 } |
| 2547 | 2361 |
| 2548 // Load the (only) argument into eax. | 2362 // Load the (only) argument into eax. |
| 2549 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2363 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2550 | 2364 |
| 2551 // Check if the argument is a smi. | 2365 // Check if the argument is a smi. |
| 2552 Label not_smi; | 2366 Label not_smi; |
| 2553 STATIC_ASSERT(kSmiTag == 0); | 2367 STATIC_ASSERT(kSmiTag == 0); |
| 2554 __ JumpIfNotSmi(eax, ¬_smi); | 2368 __ JumpIfNotSmi(eax, ¬_smi); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2597 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 2411 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
| 2598 __ ret(2 * kPointerSize); | 2412 __ ret(2 * kPointerSize); |
| 2599 | 2413 |
| 2600 // Tail call the full function. We do not have to patch the receiver | 2414 // Tail call the full function. We do not have to patch the receiver |
| 2601 // because the function makes no use of it. | 2415 // because the function makes no use of it. |
| 2602 __ bind(&slow); | 2416 __ bind(&slow); |
| 2603 ParameterCount expected(function); | 2417 ParameterCount expected(function); |
| 2604 __ InvokeFunction(function, expected, arguments(), | 2418 __ InvokeFunction(function, expected, arguments(), |
| 2605 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2419 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2606 | 2420 |
| 2607 __ bind(&miss); | 2421 HandlerFrontendFooter(&miss); |
| 2608 // ecx: function name. | |
| 2609 GenerateMissBranch(); | |
| 2610 | 2422 |
| 2611 // Return the generated code. | 2423 // Return the generated code. |
| 2612 return GetCode(type, name); | 2424 return GetCode(type, name); |
| 2613 } | 2425 } |
| 2614 | 2426 |
| 2615 | 2427 |
| 2616 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2428 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2617 const CallOptimization& optimization, | 2429 const CallOptimization& optimization, |
| 2618 Handle<Object> object, | 2430 Handle<Object> object, |
| 2619 Handle<JSObject> holder, | 2431 Handle<JSObject> holder, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2676 Label success; | 2488 Label success; |
| 2677 // Check that the object is a boolean. | 2489 // Check that the object is a boolean. |
| 2678 __ cmp(object, factory()->true_value()); | 2490 __ cmp(object, factory()->true_value()); |
| 2679 __ j(equal, &success); | 2491 __ j(equal, &success); |
| 2680 __ cmp(object, factory()->false_value()); | 2492 __ cmp(object, factory()->false_value()); |
| 2681 __ j(not_equal, miss); | 2493 __ j(not_equal, miss); |
| 2682 __ bind(&success); | 2494 __ bind(&success); |
| 2683 } | 2495 } |
| 2684 | 2496 |
| 2685 | 2497 |
| 2686 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2498 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2687 Handle<JSObject> holder, | 2499 if (object->IsGlobalObject()) { |
| 2688 Handle<Name> name, | 2500 const int argc = arguments().immediate(); |
| 2689 CheckType check) { | 2501 const int receiver_offset = (argc + 1) * kPointerSize; |
| 2690 // ----------- S t a t e ------------- | 2502 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2691 // -- ecx : name | 2503 __ mov(Operand(esp, receiver_offset), edx); |
| 2692 // -- esp[0] : return address | 2504 } |
| 2693 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2505 } |
| 2694 // -- ... | |
| 2695 // -- esp[(argc + 1) * 4] : receiver | |
| 2696 // ----------------------------------- | |
| 2697 Label miss; | |
| 2698 GenerateNameCheck(name, &miss); | |
| 2699 | 2506 |
| 2700 // Get the receiver from the stack. | 2507 |
| 2508 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | |
| 2509 Handle<JSObject> holder, | |
| 2510 Handle<Name> name, | |
| 2511 CheckType check, | |
| 2512 Label* miss) { | |
| 2513 GenerateNameCheck(name, miss); | |
| 2514 | |
| 2515 Register reg = edx; | |
| 2516 | |
| 2701 const int argc = arguments().immediate(); | 2517 const int argc = arguments().immediate(); |
| 2702 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2518 const int receiver_offset = (argc + 1) * kPointerSize; |
| 2519 __ mov(reg, Operand(esp, receiver_offset)); | |
| 2703 | 2520 |
| 2704 // Check that the receiver isn't a smi. | 2521 // Check that the receiver isn't a smi. |
| 2705 if (check != NUMBER_CHECK) { | 2522 if (check != NUMBER_CHECK) { |
| 2706 __ JumpIfSmi(edx, &miss); | 2523 __ JumpIfSmi(reg, miss); |
| 2707 } | 2524 } |
| 2708 | 2525 |
| 2709 // Make sure that it's okay not to patch the on stack receiver | 2526 // Make sure that it's okay not to patch the on stack receiver |
| 2710 // unless we're doing a receiver map check. | 2527 // unless we're doing a receiver map check. |
| 2711 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2528 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2712 switch (check) { | 2529 switch (check) { |
| 2713 case RECEIVER_MAP_CHECK: | 2530 case RECEIVER_MAP_CHECK: |
| 2714 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2531 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
| 2715 | 2532 |
| 2716 // Check that the maps haven't changed. | 2533 // Check that the maps haven't changed. |
| 2717 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, | 2534 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder, |
| 2718 ebx, eax, edi, name, &miss); | 2535 ebx, eax, edi, name, miss); |
| 2719 | 2536 |
| 2720 // Patch the receiver on the stack with the global proxy if | |
| 2721 // necessary. | |
| 2722 if (object->IsGlobalObject()) { | |
| 2723 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | |
| 2724 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | |
| 2725 } | |
| 2726 break; | 2537 break; |
| 2727 | 2538 |
| 2728 case STRING_CHECK: { | 2539 case STRING_CHECK: { |
| 2729 // Check that the object is a string. | 2540 // Check that the object is a string. |
| 2730 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2541 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax); |
| 2731 __ j(above_equal, &miss); | 2542 __ j(above_equal, miss); |
| 2732 // Check that the maps starting from the prototype haven't changed. | 2543 // Check that the maps starting from the prototype haven't changed. |
| 2733 GenerateDirectLoadGlobalFunctionPrototype( | 2544 GenerateDirectLoadGlobalFunctionPrototype( |
| 2734 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2545 masm(), Context::STRING_FUNCTION_INDEX, eax, miss); |
| 2735 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2736 CheckPrototypes( | |
| 2737 IC::CurrentTypeOf(prototype, isolate()), | |
| 2738 eax, holder, ebx, edx, edi, name, &miss); | |
| 2739 break; | 2546 break; |
| 2740 } | 2547 } |
| 2741 case SYMBOL_CHECK: { | 2548 case SYMBOL_CHECK: { |
| 2742 // Check that the object is a symbol. | 2549 // Check that the object is a symbol. |
| 2743 __ CmpObjectType(edx, SYMBOL_TYPE, eax); | 2550 __ CmpObjectType(reg, SYMBOL_TYPE, eax); |
| 2744 __ j(not_equal, &miss); | 2551 __ j(not_equal, miss); |
| 2745 // Check that the maps starting from the prototype haven't changed. | 2552 // Check that the maps starting from the prototype haven't changed. |
| 2746 GenerateDirectLoadGlobalFunctionPrototype( | 2553 GenerateDirectLoadGlobalFunctionPrototype( |
| 2747 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); | 2554 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss); |
| 2748 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2749 CheckPrototypes( | |
| 2750 IC::CurrentTypeOf(prototype, isolate()), | |
| 2751 eax, holder, ebx, edx, edi, name, &miss); | |
| 2752 break; | 2555 break; |
| 2753 } | 2556 } |
| 2754 case NUMBER_CHECK: { | 2557 case NUMBER_CHECK: { |
| 2755 Label fast; | 2558 Label fast; |
| 2756 // Check that the object is a smi or a heap number. | 2559 // Check that the object is a smi or a heap number. |
| 2757 __ JumpIfSmi(edx, &fast); | 2560 __ JumpIfSmi(reg, &fast); |
| 2758 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2561 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax); |
| 2759 __ j(not_equal, &miss); | 2562 __ j(not_equal, miss); |
| 2760 __ bind(&fast); | 2563 __ bind(&fast); |
| 2761 // Check that the maps starting from the prototype haven't changed. | 2564 // Check that the maps starting from the prototype haven't changed. |
| 2762 GenerateDirectLoadGlobalFunctionPrototype( | 2565 GenerateDirectLoadGlobalFunctionPrototype( |
| 2763 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2566 masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss); |
| 2764 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2765 CheckPrototypes( | |
| 2766 IC::CurrentTypeOf(prototype, isolate()), | |
| 2767 eax, holder, ebx, edx, edi, name, &miss); | |
| 2768 break; | 2567 break; |
| 2769 } | 2568 } |
| 2770 case BOOLEAN_CHECK: { | 2569 case BOOLEAN_CHECK: { |
| 2771 GenerateBooleanCheck(edx, &miss); | 2570 GenerateBooleanCheck(reg, miss); |
| 2772 // Check that the maps starting from the prototype haven't changed. | 2571 // Check that the maps starting from the prototype haven't changed. |
| 2773 GenerateDirectLoadGlobalFunctionPrototype( | 2572 GenerateDirectLoadGlobalFunctionPrototype( |
| 2774 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2573 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss); |
| 2775 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2776 CheckPrototypes( | |
| 2777 IC::CurrentTypeOf(prototype, isolate()), | |
| 2778 eax, holder, ebx, edx, edi, name, &miss); | |
| 2779 break; | 2574 break; |
| 2780 } | 2575 } |
| 2781 } | 2576 } |
| 2782 | 2577 |
| 2783 Label success; | 2578 if (check != RECEIVER_MAP_CHECK) { |
| 2784 __ jmp(&success); | 2579 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2580 reg = CheckPrototypes( | |
| 2581 IC::CurrentTypeOf(prototype, isolate()), | |
| 2582 eax, holder, ebx, edx, edi, name, miss); | |
| 2583 } | |
| 2785 | 2584 |
| 2786 // Handle call cache miss. | 2585 return reg; |
| 2787 __ bind(&miss); | |
| 2788 GenerateMissBranch(); | |
| 2789 | |
| 2790 __ bind(&success); | |
| 2791 } | 2586 } |
| 2792 | 2587 |
| 2793 | 2588 |
| 2794 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2589 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2795 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2590 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2796 ? CALL_AS_FUNCTION | 2591 ? CALL_AS_FUNCTION |
| 2797 : CALL_AS_METHOD; | 2592 : CALL_AS_METHOD; |
| 2798 ParameterCount expected(function); | 2593 ParameterCount expected(function); |
| 2799 __ InvokeFunction(function, expected, arguments(), | 2594 __ InvokeFunction(function, expected, arguments(), |
| 2800 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2595 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2801 } | 2596 } |
| 2802 | 2597 |
| 2803 | 2598 |
| 2804 Handle<Code> CallStubCompiler::CompileCallConstant( | 2599 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2805 Handle<Object> object, | 2600 Handle<Object> object, |
| 2806 Handle<JSObject> holder, | 2601 Handle<JSObject> holder, |
| 2807 Handle<Name> name, | 2602 Handle<Name> name, |
| 2808 CheckType check, | 2603 CheckType check, |
| 2809 Handle<JSFunction> function) { | 2604 Handle<JSFunction> function) { |
| 2810 | 2605 |
| 2811 if (HasCustomCallGenerator(function)) { | 2606 if (HasCustomCallGenerator(function)) { |
| 2812 Handle<Code> code = CompileCustomCall(object, holder, | 2607 Handle<Code> code = CompileCustomCall(object, holder, |
| 2813 Handle<Cell>::null(), | 2608 Handle<Cell>::null(), |
| 2814 function, Handle<String>::cast(name), | 2609 function, Handle<String>::cast(name), |
| 2815 Code::FAST); | 2610 Code::FAST); |
| 2816 // A null handle means bail out to the regular compiler code below. | 2611 // A null handle means bail out to the regular compiler code below. |
| 2817 if (!code.is_null()) return code; | 2612 if (!code.is_null()) return code; |
| 2818 } | 2613 } |
| 2819 | 2614 |
| 2820 CompileHandlerFrontend(object, holder, name, check); | 2615 Label miss; |
| 2616 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2617 PatchGlobalProxy(object); | |
| 2821 CompileHandlerBackend(function); | 2618 CompileHandlerBackend(function); |
| 2619 HandlerFrontendFooter(&miss); | |
| 2822 | 2620 |
| 2823 // Return the generated code. | 2621 // Return the generated code. |
| 2824 return GetCode(function); | 2622 return GetCode(function); |
| 2825 } | 2623 } |
| 2826 | 2624 |
| 2827 | 2625 |
| 2828 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2626 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2829 Handle<JSObject> holder, | 2627 Handle<JSObject> holder, |
| 2830 Handle<Name> name) { | 2628 Handle<Name> name) { |
| 2831 // ----------- S t a t e ------------- | |
| 2832 // -- ecx : name | |
| 2833 // -- esp[0] : return address | |
| 2834 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2835 // -- ... | |
| 2836 // -- esp[(argc + 1) * 4] : receiver | |
| 2837 // ----------------------------------- | |
| 2838 Label miss; | 2629 Label miss; |
| 2839 | 2630 |
| 2840 GenerateNameCheck(name, &miss); | 2631 GenerateNameCheck(name, &miss); |
| 2841 | 2632 |
| 2842 // Get the number of arguments. | 2633 // Get the number of arguments. |
| 2843 const int argc = arguments().immediate(); | 2634 const int argc = arguments().immediate(); |
| 2844 | 2635 |
| 2845 LookupResult lookup(isolate()); | 2636 LookupResult lookup(isolate()); |
| 2846 LookupPostInterceptor(holder, name, &lookup); | 2637 LookupPostInterceptor(holder, name, &lookup); |
| 2847 | 2638 |
| 2848 // Get the receiver from the stack. | 2639 // Get the receiver from the stack. |
| 2849 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2640 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2850 | 2641 |
| 2851 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); | 2642 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
| 2852 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, | 2643 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, |
| 2853 &miss); | 2644 &miss); |
| 2854 | 2645 |
| 2855 // Restore receiver. | 2646 // Restore receiver. |
| 2856 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2647 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2857 | 2648 |
| 2858 // Check that the function really is a function. | 2649 // Check that the function really is a function. |
| 2859 __ JumpIfSmi(eax, &miss); | 2650 __ JumpIfSmi(eax, &miss); |
| 2860 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2651 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 2861 __ j(not_equal, &miss); | 2652 __ j(not_equal, &miss); |
| 2862 | 2653 |
| 2863 // Patch the receiver on the stack with the global proxy if | 2654 // Patch the receiver on the stack with the global proxy if |
| 2864 // necessary. | 2655 // necessary. |
| 2865 if (object->IsGlobalObject()) { | 2656 if (object->IsGlobalObject()) { |
|
Igor Sheludko
2013/11/28 12:54:27
Looks like PatchGlobalProxy(object);
| |
| 2866 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2657 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2867 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2658 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2868 } | 2659 } |
| 2869 | 2660 |
| 2870 // Invoke the function. | 2661 // Invoke the function. |
| 2871 __ mov(edi, eax); | 2662 __ mov(edi, eax); |
| 2872 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2663 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2873 ? CALL_AS_FUNCTION | 2664 ? CALL_AS_FUNCTION |
| 2874 : CALL_AS_METHOD; | 2665 : CALL_AS_METHOD; |
| 2875 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2666 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2876 NullCallWrapper(), call_kind); | 2667 NullCallWrapper(), call_kind); |
| 2877 | 2668 |
| 2878 // Handle load cache miss. | 2669 // Handle load cache miss. |
| 2879 __ bind(&miss); | 2670 __ bind(&miss); |
| 2880 GenerateMissBranch(); | 2671 GenerateMissBranch(); |
| 2881 | 2672 |
| 2882 // Return the generated code. | 2673 // Return the generated code. |
| 2883 return GetCode(Code::FAST, name); | 2674 return GetCode(Code::FAST, name); |
| 2884 } | 2675 } |
| 2885 | 2676 |
| 2886 | 2677 |
| 2887 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2678 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2888 Handle<JSObject> object, | 2679 Handle<JSObject> object, |
| 2889 Handle<GlobalObject> holder, | 2680 Handle<GlobalObject> holder, |
| 2890 Handle<PropertyCell> cell, | 2681 Handle<PropertyCell> cell, |
| 2891 Handle<JSFunction> function, | 2682 Handle<JSFunction> function, |
| 2892 Handle<Name> name) { | 2683 Handle<Name> name) { |
| 2893 // ----------- S t a t e ------------- | |
| 2894 // -- ecx : name | |
| 2895 // -- esp[0] : return address | |
| 2896 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2897 // -- ... | |
| 2898 // -- esp[(argc + 1) * 4] : receiver | |
| 2899 // ----------------------------------- | |
| 2900 | |
| 2901 if (HasCustomCallGenerator(function)) { | 2684 if (HasCustomCallGenerator(function)) { |
| 2902 Handle<Code> code = CompileCustomCall( | 2685 Handle<Code> code = CompileCustomCall( |
| 2903 object, holder, cell, function, Handle<String>::cast(name), | 2686 object, holder, cell, function, Handle<String>::cast(name), |
| 2904 Code::NORMAL); | 2687 Code::NORMAL); |
| 2905 // A null handle means bail out to the regular compiler code below. | 2688 // A null handle means bail out to the regular compiler code below. |
| 2906 if (!code.is_null()) return code; | 2689 if (!code.is_null()) return code; |
| 2907 } | 2690 } |
| 2908 | 2691 |
| 2909 Label miss; | 2692 Label miss; |
| 2910 GenerateNameCheck(name, &miss); | 2693 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2911 | |
| 2912 // Get the number of arguments. | |
| 2913 const int argc = arguments().immediate(); | |
| 2914 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2915 GenerateLoadFunctionFromCell(cell, function, &miss); | 2694 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2916 | 2695 PatchGlobalProxy(object); |
| 2917 // Patch the receiver on the stack with the global proxy. | |
| 2918 if (object->IsGlobalObject()) { | |
| 2919 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | |
| 2920 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | |
| 2921 } | |
| 2922 | 2696 |
| 2923 // Set up the context (function already in edi). | 2697 // Set up the context (function already in edi). |
| 2924 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2698 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2925 | 2699 |
| 2926 // Jump to the cached code (tail call). | 2700 // Jump to the cached code (tail call). |
| 2927 Counters* counters = isolate()->counters(); | 2701 Counters* counters = isolate()->counters(); |
| 2928 __ IncrementCounter(counters->call_global_inline(), 1); | 2702 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2929 ParameterCount expected(function->shared()->formal_parameter_count()); | 2703 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2930 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2704 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2931 ? CALL_AS_FUNCTION | 2705 ? CALL_AS_FUNCTION |
| 2932 : CALL_AS_METHOD; | 2706 : CALL_AS_METHOD; |
| 2933 // We call indirectly through the code field in the function to | 2707 // We call indirectly through the code field in the function to |
| 2934 // allow recompilation to take effect without changing any of the | 2708 // allow recompilation to take effect without changing any of the |
| 2935 // call sites. | 2709 // call sites. |
| 2936 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2710 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2937 expected, arguments(), JUMP_FUNCTION, | 2711 expected, arguments(), JUMP_FUNCTION, |
| 2938 NullCallWrapper(), call_kind); | 2712 NullCallWrapper(), call_kind); |
| 2939 | 2713 |
| 2940 // Handle call cache miss. | 2714 HandlerFrontendFooter(&miss); |
| 2941 __ bind(&miss); | |
| 2942 __ IncrementCounter(counters->call_global_inline_miss(), 1); | |
| 2943 GenerateMissBranch(); | |
| 2944 | 2715 |
| 2945 // Return the generated code. | 2716 // Return the generated code. |
| 2946 return GetCode(Code::NORMAL, name); | 2717 return GetCode(Code::NORMAL, name); |
| 2947 } | 2718 } |
| 2948 | 2719 |
| 2949 | 2720 |
| 2950 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2721 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2951 Handle<JSObject> object, | 2722 Handle<JSObject> object, |
| 2952 Handle<JSObject> holder, | 2723 Handle<JSObject> holder, |
| 2953 Handle<Name> name, | 2724 Handle<Name> name, |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3307 // ----------------------------------- | 3078 // ----------------------------------- |
| 3308 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3079 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3309 } | 3080 } |
| 3310 | 3081 |
| 3311 | 3082 |
| 3312 #undef __ | 3083 #undef __ |
| 3313 | 3084 |
| 3314 } } // namespace v8::internal | 3085 } } // namespace v8::internal |
| 3315 | 3086 |
| 3316 #endif // V8_TARGET_ARCH_IA32 | 3087 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |