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