| 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 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 ApiParameterOperand(1), | 638 ApiParameterOperand(1), |
| 639 argc + kFastApiCallArguments + 1, | 639 argc + kFastApiCallArguments + 1, |
| 640 return_value_operand, | 640 return_value_operand, |
| 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(CallStubCompiler* stub_compiler, |
| 649 const ParameterCount& arguments, | 649 const ParameterCount& arguments, |
| 650 Register name, | 650 Register name, |
| 651 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) {} | |
| 656 | 655 |
| 657 void Compile(MacroAssembler* masm, | 656 void Compile(MacroAssembler* masm, |
| 658 Handle<JSObject> object, | 657 Handle<JSObject> object, |
| 659 Handle<JSObject> holder, | 658 Handle<JSObject> holder, |
| 660 Handle<Name> name, | 659 Handle<Name> name, |
| 661 LookupResult* lookup, | 660 LookupResult* lookup, |
| 662 Register receiver, | 661 Register receiver, |
| 663 Register scratch1, | 662 Register scratch1, |
| 664 Register scratch2, | 663 Register scratch2, |
| 665 Register scratch3, | 664 Register scratch3, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 // for API (object which is instanceof for the signature). It's | 748 // for API (object which is instanceof for the signature). It's |
| 750 // safe to omit it here, as if present, it should be fetched | 749 // safe to omit it here, as if present, it should be fetched |
| 751 // by the previous CheckPrototypes. | 750 // by the previous CheckPrototypes. |
| 752 ASSERT(depth2 == kInvalidProtoDepth); | 751 ASSERT(depth2 == kInvalidProtoDepth); |
| 753 } | 752 } |
| 754 | 753 |
| 755 // Invoke function. | 754 // Invoke function. |
| 756 if (can_do_fast_api_call) { | 755 if (can_do_fast_api_call) { |
| 757 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 756 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 758 } else { | 757 } else { |
| 759 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 758 Handle<JSFunction> fun = optimization.constant_function(); |
| 760 ? CALL_AS_FUNCTION | 759 stub_compiler_->GenerateJumpFunctionIgnoreReceiver(fun); |
| 761 : CALL_AS_METHOD; | |
| 762 Handle<JSFunction> function = optimization.constant_function(); | |
| 763 ParameterCount expected(function); | |
| 764 __ InvokeFunction(function, expected, arguments_, | |
| 765 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 766 } | 760 } |
| 767 | 761 |
| 768 // Deferred code for fast API call case---clean preallocated space. | 762 // Deferred code for fast API call case---clean preallocated space. |
| 769 if (can_do_fast_api_call) { | 763 if (can_do_fast_api_call) { |
| 770 __ bind(&miss_cleanup); | 764 __ bind(&miss_cleanup); |
| 771 FreeSpaceForFastApiCall(masm, scratch1); | 765 FreeSpaceForFastApiCall(masm, scratch1); |
| 772 __ jmp(miss_label); | 766 __ jmp(miss_label); |
| 773 } | 767 } |
| 774 | 768 |
| 775 // Invoke a regular function. | 769 // Invoke a regular function. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 | 817 |
| 824 __ pop(name_); // Restore the name. | 818 __ pop(name_); // Restore the name. |
| 825 __ pop(receiver); // Restore the holder. | 819 __ pop(receiver); // Restore the holder. |
| 826 // Leave the internal frame. | 820 // Leave the internal frame. |
| 827 } | 821 } |
| 828 | 822 |
| 829 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 823 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
| 830 __ j(not_equal, interceptor_succeeded); | 824 __ j(not_equal, interceptor_succeeded); |
| 831 } | 825 } |
| 832 | 826 |
| 833 StubCompiler* stub_compiler_; | 827 CallStubCompiler* stub_compiler_; |
| 834 const ParameterCount& arguments_; | 828 const ParameterCount& arguments_; |
| 835 Register name_; | 829 Register name_; |
| 836 ExtraICState extra_state_; | |
| 837 }; | 830 }; |
| 838 | 831 |
| 839 | 832 |
| 840 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 833 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 841 Label* label, | 834 Label* label, |
| 842 Handle<Name> name) { | 835 Handle<Name> name) { |
| 843 if (!label->is_unused()) { | 836 if (!label->is_unused()) { |
| 844 __ bind(label); | 837 __ bind(label); |
| 845 __ mov(this->name(), Immediate(name)); | 838 __ mov(this->name(), Immediate(name)); |
| 846 } | 839 } |
| (...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 | 1588 |
| 1596 | 1589 |
| 1597 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1590 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1598 if (kind_ == Code::KEYED_CALL_IC) { | 1591 if (kind_ == Code::KEYED_CALL_IC) { |
| 1599 __ cmp(ecx, Immediate(name)); | 1592 __ cmp(ecx, Immediate(name)); |
| 1600 __ j(not_equal, miss); | 1593 __ j(not_equal, miss); |
| 1601 } | 1594 } |
| 1602 } | 1595 } |
| 1603 | 1596 |
| 1604 | 1597 |
| 1598 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1599 Register scratch, |
| 1600 Label* miss) { |
| 1601 __ JumpIfSmi(function, miss); |
| 1602 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 1603 __ j(not_equal, miss); |
| 1604 } |
| 1605 |
| 1606 |
| 1605 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1607 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1606 Handle<Cell> cell, | 1608 Handle<Cell> cell, |
| 1607 Handle<JSFunction> function, | 1609 Handle<JSFunction> function, |
| 1608 Label* miss) { | 1610 Label* miss) { |
| 1609 // Get the value from the cell. | 1611 // Get the value from the cell. |
| 1610 if (Serializer::enabled()) { | 1612 if (Serializer::enabled()) { |
| 1611 __ mov(edi, Immediate(cell)); | 1613 __ mov(edi, Immediate(cell)); |
| 1612 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); | 1614 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); |
| 1613 } else { | 1615 } else { |
| 1614 __ mov(edi, Operand::ForCell(cell)); | 1616 __ mov(edi, Operand::ForCell(cell)); |
| 1615 } | 1617 } |
| 1616 | 1618 |
| 1617 // Check that the cell contains the same function. | 1619 // Check that the cell contains the same function. |
| 1618 if (isolate()->heap()->InNewSpace(*function)) { | 1620 if (isolate()->heap()->InNewSpace(*function)) { |
| 1619 // We can't embed a pointer to a function in new space so we have | 1621 // We can't embed a pointer to a function in new space so we have |
| 1620 // to verify that the shared function info is unchanged. This has | 1622 // to verify that the shared function info is unchanged. This has |
| 1621 // the nice side effect that multiple closures based on the same | 1623 // the nice side effect that multiple closures based on the same |
| 1622 // function can all use this call IC. Before we load through the | 1624 // function can all use this call IC. Before we load through the |
| 1623 // function, we have to verify that it still is a function. | 1625 // function, we have to verify that it still is a function. |
| 1624 __ JumpIfSmi(edi, miss); | 1626 GenerateFunctionCheck(edi, ebx, miss); |
| 1625 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
| 1626 __ j(not_equal, miss); | |
| 1627 | 1627 |
| 1628 // Check the shared function info. Make sure it hasn't changed. | 1628 // Check the shared function info. Make sure it hasn't changed. |
| 1629 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1629 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1630 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1630 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1631 } else { | 1631 } else { |
| 1632 __ cmp(edi, Immediate(function)); | 1632 __ cmp(edi, Immediate(function)); |
| 1633 } | 1633 } |
| 1634 __ j(not_equal, miss); | 1634 __ j(not_equal, miss); |
| 1635 } | 1635 } |
| 1636 | 1636 |
| 1637 | 1637 |
| 1638 void CallStubCompiler::GenerateMissBranch() { | 1638 void CallStubCompiler::GenerateMissBranch() { |
| 1639 Handle<Code> code = | 1639 Handle<Code> code = |
| 1640 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1640 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1641 kind_, | 1641 kind_, |
| 1642 extra_state_); | 1642 extra_state()); |
| 1643 __ jmp(code, RelocInfo::CODE_TARGET); | 1643 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1644 } | 1644 } |
| 1645 | 1645 |
| 1646 | 1646 |
| 1647 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1647 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1648 Handle<JSObject> holder, | 1648 Handle<JSObject> holder, |
| 1649 PropertyIndex index, | 1649 PropertyIndex index, |
| 1650 Handle<Name> name) { | 1650 Handle<Name> name) { |
| 1651 Label miss; | 1651 Label miss; |
| 1652 | 1652 |
| 1653 Register reg = HandlerFrontendHeader( | 1653 Register reg = HandlerFrontendHeader( |
| 1654 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1654 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1655 | 1655 |
| 1656 GenerateFastPropertyLoad( | 1656 GenerateFastPropertyLoad( |
| 1657 masm(), edi, reg, index.is_inobject(holder), | 1657 masm(), edi, reg, index.is_inobject(holder), |
| 1658 index.translate(holder), Representation::Tagged()); | 1658 index.translate(holder), Representation::Tagged()); |
| 1659 | 1659 GenerateJumpFunction(object, edi, &miss); |
| 1660 // Check that the function really is a function. | |
| 1661 __ JumpIfSmi(edi, &miss); | |
| 1662 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
| 1663 __ j(not_equal, &miss); | |
| 1664 | |
| 1665 PatchGlobalProxy(object); | |
| 1666 | |
| 1667 // Invoke the function. | |
| 1668 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 1669 ? CALL_AS_FUNCTION | |
| 1670 : CALL_AS_METHOD; | |
| 1671 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | |
| 1672 NullCallWrapper(), call_kind); | |
| 1673 | 1660 |
| 1674 HandlerFrontendFooter(&miss); | 1661 HandlerFrontendFooter(&miss); |
| 1675 | 1662 |
| 1676 // Return the generated code. | 1663 // Return the generated code. |
| 1677 return GetCode(Code::FAST, name); | 1664 return GetCode(Code::FAST, name); |
| 1678 } | 1665 } |
| 1679 | 1666 |
| 1680 | 1667 |
| 1681 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1668 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1682 Handle<Object> object, | 1669 Handle<Object> object, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1711 } | 1698 } |
| 1712 | 1699 |
| 1713 | 1700 |
| 1714 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1701 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1715 Handle<Object> object, | 1702 Handle<Object> object, |
| 1716 Handle<JSObject> holder, | 1703 Handle<JSObject> holder, |
| 1717 Handle<Cell> cell, | 1704 Handle<Cell> cell, |
| 1718 Handle<JSFunction> function, | 1705 Handle<JSFunction> function, |
| 1719 Handle<String> name, | 1706 Handle<String> name, |
| 1720 Code::StubType type) { | 1707 Code::StubType type) { |
| 1721 // If object is not an array or is observed, bail out to regular call. | 1708 // If object is not an array or is observed or sealed, bail out to regular |
| 1709 // call. |
| 1722 if (!object->IsJSArray() || | 1710 if (!object->IsJSArray() || |
| 1723 !cell.is_null() || | 1711 !cell.is_null() || |
| 1724 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1712 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1713 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1725 return Handle<Code>::null(); | 1714 return Handle<Code>::null(); |
| 1726 } | 1715 } |
| 1727 | 1716 |
| 1728 Label miss; | 1717 Label miss; |
| 1729 | 1718 |
| 1730 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1719 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1731 | 1720 |
| 1732 const int argc = arguments().immediate(); | 1721 const int argc = arguments().immediate(); |
| 1733 if (argc == 0) { | 1722 if (argc == 0) { |
| 1734 // Noop, return the length. | 1723 // Noop, return the length. |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1954 } | 1943 } |
| 1955 | 1944 |
| 1956 | 1945 |
| 1957 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1946 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1958 Handle<Object> object, | 1947 Handle<Object> object, |
| 1959 Handle<JSObject> holder, | 1948 Handle<JSObject> holder, |
| 1960 Handle<Cell> cell, | 1949 Handle<Cell> cell, |
| 1961 Handle<JSFunction> function, | 1950 Handle<JSFunction> function, |
| 1962 Handle<String> name, | 1951 Handle<String> name, |
| 1963 Code::StubType type) { | 1952 Code::StubType type) { |
| 1964 // If object is not an array or is observed, bail out to regular call. | 1953 // If object is not an array or is observed or sealed, bail out to regular |
| 1954 // call. |
| 1965 if (!object->IsJSArray() || | 1955 if (!object->IsJSArray() || |
| 1966 !cell.is_null() || | 1956 !cell.is_null() || |
| 1967 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1957 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1958 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1968 return Handle<Code>::null(); | 1959 return Handle<Code>::null(); |
| 1969 } | 1960 } |
| 1970 | 1961 |
| 1971 Label miss, return_undefined, call_builtin; | 1962 Label miss, return_undefined, call_builtin; |
| 1972 | 1963 |
| 1973 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1964 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1974 | 1965 |
| 1975 // Get the elements array of the object. | 1966 // Get the elements array of the object. |
| 1976 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1967 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 1977 | 1968 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2035 } | 2026 } |
| 2036 | 2027 |
| 2037 const int argc = arguments().immediate(); | 2028 const int argc = arguments().immediate(); |
| 2038 | 2029 |
| 2039 Label miss; | 2030 Label miss; |
| 2040 Label name_miss; | 2031 Label name_miss; |
| 2041 Label index_out_of_range; | 2032 Label index_out_of_range; |
| 2042 Label* index_out_of_range_label = &index_out_of_range; | 2033 Label* index_out_of_range_label = &index_out_of_range; |
| 2043 | 2034 |
| 2044 if (kind_ == Code::CALL_IC && | 2035 if (kind_ == Code::CALL_IC && |
| 2045 (CallICBase::StringStubState::decode(extra_state_) == | 2036 (CallICBase::StringStubState::decode(extra_state()) == |
| 2046 DEFAULT_STRING_STUB)) { | 2037 DEFAULT_STRING_STUB)) { |
| 2047 index_out_of_range_label = &miss; | 2038 index_out_of_range_label = &miss; |
| 2048 } | 2039 } |
| 2049 | 2040 |
| 2050 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 2041 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2051 | 2042 |
| 2052 Register receiver = ebx; | 2043 Register receiver = ebx; |
| 2053 Register index = edi; | 2044 Register index = edi; |
| 2054 Register result = eax; | 2045 Register result = eax; |
| 2055 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2046 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2074 | 2065 |
| 2075 if (index_out_of_range.is_linked()) { | 2066 if (index_out_of_range.is_linked()) { |
| 2076 __ bind(&index_out_of_range); | 2067 __ bind(&index_out_of_range); |
| 2077 __ Set(eax, Immediate(factory()->nan_value())); | 2068 __ Set(eax, Immediate(factory()->nan_value())); |
| 2078 __ ret((argc + 1) * kPointerSize); | 2069 __ ret((argc + 1) * kPointerSize); |
| 2079 } | 2070 } |
| 2080 | 2071 |
| 2081 __ bind(&miss); | 2072 __ bind(&miss); |
| 2082 // Restore function name in ecx. | 2073 // Restore function name in ecx. |
| 2083 __ Set(ecx, Immediate(name)); | 2074 __ Set(ecx, Immediate(name)); |
| 2084 __ bind(&name_miss); | 2075 HandlerFrontendFooter(&name_miss); |
| 2085 GenerateMissBranch(); | |
| 2086 | 2076 |
| 2087 // Return the generated code. | 2077 // Return the generated code. |
| 2088 return GetCode(type, name); | 2078 return GetCode(type, name); |
| 2089 } | 2079 } |
| 2090 | 2080 |
| 2091 | 2081 |
| 2092 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2082 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2093 Handle<Object> object, | 2083 Handle<Object> object, |
| 2094 Handle<JSObject> holder, | 2084 Handle<JSObject> holder, |
| 2095 Handle<Cell> cell, | 2085 Handle<Cell> cell, |
| 2096 Handle<JSFunction> function, | 2086 Handle<JSFunction> function, |
| 2097 Handle<String> name, | 2087 Handle<String> name, |
| 2098 Code::StubType type) { | 2088 Code::StubType type) { |
| 2099 // If object is not a string, bail out to regular call. | 2089 // If object is not a string, bail out to regular call. |
| 2100 if (!object->IsString() || !cell.is_null()) { | 2090 if (!object->IsString() || !cell.is_null()) { |
| 2101 return Handle<Code>::null(); | 2091 return Handle<Code>::null(); |
| 2102 } | 2092 } |
| 2103 | 2093 |
| 2104 const int argc = arguments().immediate(); | 2094 const int argc = arguments().immediate(); |
| 2105 | 2095 |
| 2106 Label miss; | 2096 Label miss; |
| 2107 Label name_miss; | 2097 Label name_miss; |
| 2108 Label index_out_of_range; | 2098 Label index_out_of_range; |
| 2109 Label* index_out_of_range_label = &index_out_of_range; | 2099 Label* index_out_of_range_label = &index_out_of_range; |
| 2110 | 2100 |
| 2111 if (kind_ == Code::CALL_IC && | 2101 if (kind_ == Code::CALL_IC && |
| 2112 (CallICBase::StringStubState::decode(extra_state_) == | 2102 (CallICBase::StringStubState::decode(extra_state()) == |
| 2113 DEFAULT_STRING_STUB)) { | 2103 DEFAULT_STRING_STUB)) { |
| 2114 index_out_of_range_label = &miss; | 2104 index_out_of_range_label = &miss; |
| 2115 } | 2105 } |
| 2116 | 2106 |
| 2117 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 2107 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2118 | 2108 |
| 2119 Register receiver = eax; | 2109 Register receiver = eax; |
| 2120 Register index = edi; | 2110 Register index = edi; |
| 2121 Register scratch = edx; | 2111 Register scratch = edx; |
| 2122 Register result = eax; | 2112 Register result = eax; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2143 | 2133 |
| 2144 if (index_out_of_range.is_linked()) { | 2134 if (index_out_of_range.is_linked()) { |
| 2145 __ bind(&index_out_of_range); | 2135 __ bind(&index_out_of_range); |
| 2146 __ Set(eax, Immediate(factory()->empty_string())); | 2136 __ Set(eax, Immediate(factory()->empty_string())); |
| 2147 __ ret((argc + 1) * kPointerSize); | 2137 __ ret((argc + 1) * kPointerSize); |
| 2148 } | 2138 } |
| 2149 | 2139 |
| 2150 __ bind(&miss); | 2140 __ bind(&miss); |
| 2151 // Restore function name in ecx. | 2141 // Restore function name in ecx. |
| 2152 __ Set(ecx, Immediate(name)); | 2142 __ Set(ecx, Immediate(name)); |
| 2153 __ bind(&name_miss); | 2143 HandlerFrontendFooter(&name_miss); |
| 2154 GenerateMissBranch(); | |
| 2155 | 2144 |
| 2156 // Return the generated code. | 2145 // Return the generated code. |
| 2157 return GetCode(type, name); | 2146 return GetCode(type, name); |
| 2158 } | 2147 } |
| 2159 | 2148 |
| 2160 | 2149 |
| 2161 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2150 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2162 Handle<Object> object, | 2151 Handle<Object> object, |
| 2163 Handle<JSObject> holder, | 2152 Handle<JSObject> holder, |
| 2164 Handle<Cell> cell, | 2153 Handle<Cell> cell, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2193 // Convert the smi code to uint16. | 2182 // Convert the smi code to uint16. |
| 2194 __ and_(code, Immediate(Smi::FromInt(0xffff))); | 2183 __ and_(code, Immediate(Smi::FromInt(0xffff))); |
| 2195 | 2184 |
| 2196 StringCharFromCodeGenerator generator(code, eax); | 2185 StringCharFromCodeGenerator generator(code, eax); |
| 2197 generator.GenerateFast(masm()); | 2186 generator.GenerateFast(masm()); |
| 2198 __ ret(2 * kPointerSize); | 2187 __ ret(2 * kPointerSize); |
| 2199 | 2188 |
| 2200 StubRuntimeCallHelper call_helper; | 2189 StubRuntimeCallHelper call_helper; |
| 2201 generator.GenerateSlow(masm(), call_helper); | 2190 generator.GenerateSlow(masm(), call_helper); |
| 2202 | 2191 |
| 2203 // Tail call the full function. We do not have to patch the receiver | |
| 2204 // because the function makes no use of it. | |
| 2205 __ bind(&slow); | 2192 __ bind(&slow); |
| 2206 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2193 // We do not have to patch the receiver because the function makes no use of |
| 2207 ? CALL_AS_FUNCTION | 2194 // it. |
| 2208 : CALL_AS_METHOD; | 2195 GenerateJumpFunctionIgnoreReceiver(function); |
| 2209 ParameterCount expected(function); | |
| 2210 __ InvokeFunction(function, expected, arguments(), | |
| 2211 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2212 | 2196 |
| 2213 HandlerFrontendFooter(&miss); | 2197 HandlerFrontendFooter(&miss); |
| 2214 | 2198 |
| 2215 // Return the generated code. | 2199 // Return the generated code. |
| 2216 return GetCode(type, name); | 2200 return GetCode(type, name); |
| 2217 } | 2201 } |
| 2218 | 2202 |
| 2219 | 2203 |
| 2220 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2204 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2221 Handle<Object> object, | 2205 Handle<Object> object, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 // Return a new heap number. | 2292 // Return a new heap number. |
| 2309 __ AllocateHeapNumber(eax, ebx, edx, &slow); | 2293 __ AllocateHeapNumber(eax, ebx, edx, &slow); |
| 2310 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2294 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 2311 __ ret(2 * kPointerSize); | 2295 __ ret(2 * kPointerSize); |
| 2312 | 2296 |
| 2313 // Return the argument (when it's an already round heap number). | 2297 // Return the argument (when it's an already round heap number). |
| 2314 __ bind(&already_round); | 2298 __ bind(&already_round); |
| 2315 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2299 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2316 __ ret(2 * kPointerSize); | 2300 __ ret(2 * kPointerSize); |
| 2317 | 2301 |
| 2318 // Tail call the full function. We do not have to patch the receiver | |
| 2319 // because the function makes no use of it. | |
| 2320 __ bind(&slow); | 2302 __ bind(&slow); |
| 2321 ParameterCount expected(function); | 2303 // We do not have to patch the receiver because the function makes no use of |
| 2322 __ InvokeFunction(function, expected, arguments(), | 2304 // it. |
| 2323 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2305 GenerateJumpFunctionIgnoreReceiver(function); |
| 2324 | 2306 |
| 2325 HandlerFrontendFooter(&miss); | 2307 HandlerFrontendFooter(&miss); |
| 2326 | 2308 |
| 2327 // Return the generated code. | 2309 // Return the generated code. |
| 2328 return GetCode(type, name); | 2310 return GetCode(type, name); |
| 2329 } | 2311 } |
| 2330 | 2312 |
| 2331 | 2313 |
| 2332 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2314 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2333 Handle<Object> object, | 2315 Handle<Object> object, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2397 // If the argument is negative, clear the sign, and return a new | 2379 // If the argument is negative, clear the sign, and return a new |
| 2398 // number. | 2380 // number. |
| 2399 __ bind(&negative_sign); | 2381 __ bind(&negative_sign); |
| 2400 __ and_(ebx, ~HeapNumber::kSignMask); | 2382 __ and_(ebx, ~HeapNumber::kSignMask); |
| 2401 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | 2383 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); |
| 2402 __ AllocateHeapNumber(eax, edi, edx, &slow); | 2384 __ AllocateHeapNumber(eax, edi, edx, &slow); |
| 2403 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); | 2385 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); |
| 2404 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 2386 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
| 2405 __ ret(2 * kPointerSize); | 2387 __ ret(2 * kPointerSize); |
| 2406 | 2388 |
| 2407 // Tail call the full function. We do not have to patch the receiver | |
| 2408 // because the function makes no use of it. | |
| 2409 __ bind(&slow); | 2389 __ bind(&slow); |
| 2410 ParameterCount expected(function); | 2390 // We do not have to patch the receiver because the function makes no use of |
| 2411 __ InvokeFunction(function, expected, arguments(), | 2391 // it. |
| 2412 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2392 GenerateJumpFunctionIgnoreReceiver(function); |
| 2413 | 2393 |
| 2414 HandlerFrontendFooter(&miss); | 2394 HandlerFrontendFooter(&miss); |
| 2415 | 2395 |
| 2416 // Return the generated code. | 2396 // Return the generated code. |
| 2417 return GetCode(type, name); | 2397 return GetCode(type, name); |
| 2418 } | 2398 } |
| 2419 | 2399 |
| 2420 | 2400 |
| 2421 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2401 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2422 const CallOptimization& optimization, | 2402 const CallOptimization& optimization, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2462 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2442 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
| 2463 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2443 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2464 | 2444 |
| 2465 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2445 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2466 // duplicate of return address and will be overwritten. | 2446 // duplicate of return address and will be overwritten. |
| 2467 GenerateFastApiCall(masm(), optimization, argc); | 2447 GenerateFastApiCall(masm(), optimization, argc); |
| 2468 | 2448 |
| 2469 __ bind(&miss); | 2449 __ bind(&miss); |
| 2470 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2450 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2471 | 2451 |
| 2472 __ bind(&miss_before_stack_reserved); | 2452 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2473 GenerateMissBranch(); | |
| 2474 | 2453 |
| 2475 // Return the generated code. | 2454 // Return the generated code. |
| 2476 return GetCode(function); | 2455 return GetCode(function); |
| 2477 } | 2456 } |
| 2478 | 2457 |
| 2479 | 2458 |
| 2480 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2459 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2481 Label success; | 2460 Label success; |
| 2482 // Check that the object is a boolean. | 2461 // Check that the object is a boolean. |
| 2483 __ cmp(object, factory()->true_value()); | 2462 __ cmp(object, factory()->true_value()); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2572 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2551 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2573 reg = CheckPrototypes( | 2552 reg = CheckPrototypes( |
| 2574 IC::CurrentTypeOf(prototype, isolate()), | 2553 IC::CurrentTypeOf(prototype, isolate()), |
| 2575 eax, holder, ebx, edx, edi, name, miss); | 2554 eax, holder, ebx, edx, edi, name, miss); |
| 2576 } | 2555 } |
| 2577 | 2556 |
| 2578 return reg; | 2557 return reg; |
| 2579 } | 2558 } |
| 2580 | 2559 |
| 2581 | 2560 |
| 2582 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2561 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2583 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2562 Register function, |
| 2584 ? CALL_AS_FUNCTION | 2563 Label* miss) { |
| 2585 : CALL_AS_METHOD; | 2564 // Check that the function really is a function. |
| 2586 ParameterCount expected(function); | 2565 GenerateFunctionCheck(function, ebx, miss); |
| 2587 __ InvokeFunction(function, expected, arguments(), | 2566 |
| 2588 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2567 if (!function.is(edi)) __ mov(edi, function); |
| 2568 PatchGlobalProxy(object); |
| 2569 |
| 2570 // Invoke the function. |
| 2571 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2572 NullCallWrapper(), call_kind()); |
| 2589 } | 2573 } |
| 2590 | 2574 |
| 2591 | 2575 |
| 2592 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2593 Handle<Object> object, | |
| 2594 Handle<JSObject> holder, | |
| 2595 Handle<Name> name, | |
| 2596 CheckType check, | |
| 2597 Handle<JSFunction> function) { | |
| 2598 | |
| 2599 if (HasCustomCallGenerator(function)) { | |
| 2600 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2601 Handle<Cell>::null(), | |
| 2602 function, Handle<String>::cast(name), | |
| 2603 Code::FAST); | |
| 2604 // A null handle means bail out to the regular compiler code below. | |
| 2605 if (!code.is_null()) return code; | |
| 2606 } | |
| 2607 | |
| 2608 Label miss; | |
| 2609 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2610 PatchGlobalProxy(object); | |
| 2611 CompileHandlerBackend(function); | |
| 2612 HandlerFrontendFooter(&miss); | |
| 2613 | |
| 2614 // Return the generated code. | |
| 2615 return GetCode(function); | |
| 2616 } | |
| 2617 | |
| 2618 | |
| 2619 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2576 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2620 Handle<JSObject> holder, | 2577 Handle<JSObject> holder, |
| 2621 Handle<Name> name) { | 2578 Handle<Name> name) { |
| 2622 Label miss; | 2579 Label miss; |
| 2623 | 2580 |
| 2624 GenerateNameCheck(name, &miss); | 2581 GenerateNameCheck(name, &miss); |
| 2625 | 2582 |
| 2626 // Get the number of arguments. | 2583 // Get the number of arguments. |
| 2627 const int argc = arguments().immediate(); | 2584 const int argc = arguments().immediate(); |
| 2628 | 2585 |
| 2629 LookupResult lookup(isolate()); | 2586 LookupResult lookup(isolate()); |
| 2630 LookupPostInterceptor(holder, name, &lookup); | 2587 LookupPostInterceptor(holder, name, &lookup); |
| 2631 | 2588 |
| 2632 // Get the receiver from the stack. | 2589 // Get the receiver from the stack. |
| 2633 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2590 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2634 | 2591 |
| 2635 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); | 2592 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state()); |
| 2636 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, | 2593 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, |
| 2637 &miss); | 2594 &miss); |
| 2638 | 2595 |
| 2639 // Restore receiver. | 2596 // Restore receiver. |
| 2640 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2597 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2641 | 2598 |
| 2642 // Check that the function really is a function. | 2599 GenerateJumpFunction(object, eax, &miss); |
| 2643 __ JumpIfSmi(eax, &miss); | |
| 2644 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | |
| 2645 __ j(not_equal, &miss); | |
| 2646 | 2600 |
| 2647 // Patch the receiver on the stack with the global proxy if | 2601 HandlerFrontendFooter(&miss); |
| 2648 // necessary. | |
| 2649 if (object->IsGlobalObject()) { | |
| 2650 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | |
| 2651 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | |
| 2652 } | |
| 2653 | |
| 2654 // Invoke the function. | |
| 2655 __ mov(edi, eax); | |
| 2656 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2657 ? CALL_AS_FUNCTION | |
| 2658 : CALL_AS_METHOD; | |
| 2659 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | |
| 2660 NullCallWrapper(), call_kind); | |
| 2661 | |
| 2662 // Handle load cache miss. | |
| 2663 __ bind(&miss); | |
| 2664 GenerateMissBranch(); | |
| 2665 | 2602 |
| 2666 // Return the generated code. | 2603 // Return the generated code. |
| 2667 return GetCode(Code::FAST, name); | 2604 return GetCode(Code::FAST, name); |
| 2668 } | 2605 } |
| 2669 | 2606 |
| 2670 | 2607 |
| 2671 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2608 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2672 Handle<JSObject> object, | 2609 Handle<JSObject> object, |
| 2673 Handle<GlobalObject> holder, | 2610 Handle<GlobalObject> holder, |
| 2674 Handle<PropertyCell> cell, | 2611 Handle<PropertyCell> cell, |
| 2675 Handle<JSFunction> function, | 2612 Handle<JSFunction> function, |
| 2676 Handle<Name> name) { | 2613 Handle<Name> name) { |
| 2677 if (HasCustomCallGenerator(function)) { | 2614 if (HasCustomCallGenerator(function)) { |
| 2678 Handle<Code> code = CompileCustomCall( | 2615 Handle<Code> code = CompileCustomCall( |
| 2679 object, holder, cell, function, Handle<String>::cast(name), | 2616 object, holder, cell, function, Handle<String>::cast(name), |
| 2680 Code::NORMAL); | 2617 Code::NORMAL); |
| 2681 // A null handle means bail out to the regular compiler code below. | 2618 // A null handle means bail out to the regular compiler code below. |
| 2682 if (!code.is_null()) return code; | 2619 if (!code.is_null()) return code; |
| 2683 } | 2620 } |
| 2684 | 2621 |
| 2685 Label miss; | 2622 Label miss; |
| 2686 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2623 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2624 // Potentially loads a closure that matches the shared function info of the |
| 2625 // function, rather than function. |
| 2687 GenerateLoadFunctionFromCell(cell, function, &miss); | 2626 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2688 PatchGlobalProxy(object); | 2627 GenerateJumpFunction(object, edi, function); |
| 2689 | |
| 2690 // Set up the context (function already in edi). | |
| 2691 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | |
| 2692 | |
| 2693 // Jump to the cached code (tail call). | |
| 2694 Counters* counters = isolate()->counters(); | |
| 2695 __ IncrementCounter(counters->call_global_inline(), 1); | |
| 2696 ParameterCount expected(function->shared()->formal_parameter_count()); | |
| 2697 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2698 ? CALL_AS_FUNCTION | |
| 2699 : CALL_AS_METHOD; | |
| 2700 // We call indirectly through the code field in the function to | |
| 2701 // allow recompilation to take effect without changing any of the | |
| 2702 // call sites. | |
| 2703 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | |
| 2704 expected, arguments(), JUMP_FUNCTION, | |
| 2705 NullCallWrapper(), call_kind); | |
| 2706 | 2628 |
| 2707 HandlerFrontendFooter(&miss); | 2629 HandlerFrontendFooter(&miss); |
| 2708 | 2630 |
| 2709 // Return the generated code. | 2631 // Return the generated code. |
| 2710 return GetCode(Code::NORMAL, name); | 2632 return GetCode(Code::NORMAL, name); |
| 2711 } | 2633 } |
| 2712 | 2634 |
| 2713 | 2635 |
| 2714 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2636 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2715 Handle<JSObject> object, | 2637 Handle<JSObject> object, |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 // ----------------------------------- | 2992 // ----------------------------------- |
| 3071 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2993 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3072 } | 2994 } |
| 3073 | 2995 |
| 3074 | 2996 |
| 3075 #undef __ | 2997 #undef __ |
| 3076 | 2998 |
| 3077 } } // namespace v8::internal | 2999 } } // namespace v8::internal |
| 3078 | 3000 |
| 3079 #endif // V8_TARGET_ARCH_IA32 | 3001 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |