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