| 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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 thunk_address, | 630 thunk_address, |
| 631 callback_arg, | 631 callback_arg, |
| 632 argc + kFastApiCallArguments + 1, | 632 argc + kFastApiCallArguments + 1, |
| 633 return_value_operand, | 633 return_value_operand, |
| 634 restore_context ? &context_restore_operand : NULL); | 634 restore_context ? &context_restore_operand : NULL); |
| 635 } | 635 } |
| 636 | 636 |
| 637 | 637 |
| 638 class CallInterceptorCompiler BASE_EMBEDDED { | 638 class CallInterceptorCompiler BASE_EMBEDDED { |
| 639 public: | 639 public: |
| 640 CallInterceptorCompiler(StubCompiler* stub_compiler, | 640 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 641 const ParameterCount& arguments, | 641 const ParameterCount& arguments, |
| 642 Register name, | 642 Register name, |
| 643 ExtraICState extra_ic_state) | 643 ExtraICState extra_ic_state) |
| 644 : stub_compiler_(stub_compiler), | 644 : stub_compiler_(stub_compiler), |
| 645 arguments_(arguments), | 645 arguments_(arguments), |
| 646 name_(name), | 646 name_(name), |
| 647 extra_ic_state_(extra_ic_state) {} | 647 extra_ic_state_(extra_ic_state) {} |
| 648 | 648 |
| 649 void Compile(MacroAssembler* masm, | 649 void Compile(MacroAssembler* masm, |
| 650 Handle<JSObject> object, | 650 Handle<JSObject> object, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 // for API (object which is instanceof for the signature). It's | 741 // for API (object which is instanceof for the signature). It's |
| 742 // safe to omit it here, as if present, it should be fetched | 742 // safe to omit it here, as if present, it should be fetched |
| 743 // by the previous CheckPrototypes. | 743 // by the previous CheckPrototypes. |
| 744 ASSERT(depth2 == kInvalidProtoDepth); | 744 ASSERT(depth2 == kInvalidProtoDepth); |
| 745 } | 745 } |
| 746 | 746 |
| 747 // Invoke function. | 747 // Invoke function. |
| 748 if (can_do_fast_api_call) { | 748 if (can_do_fast_api_call) { |
| 749 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 749 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 750 } else { | 750 } else { |
| 751 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 752 ? CALL_AS_FUNCTION | |
| 753 : CALL_AS_METHOD; | |
| 754 Handle<JSFunction> fun = optimization.constant_function(); | 751 Handle<JSFunction> fun = optimization.constant_function(); |
| 755 ParameterCount expected(fun); | 752 stub_compiler_->GenerateJumpFunctionIgnoreReceiver(fun); |
| 756 __ InvokeFunction(fun, expected, arguments_, | |
| 757 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 758 } | 753 } |
| 759 | 754 |
| 760 // Deferred code for fast API call case---clean preallocated space. | 755 // Deferred code for fast API call case---clean preallocated space. |
| 761 if (can_do_fast_api_call) { | 756 if (can_do_fast_api_call) { |
| 762 __ bind(&miss_cleanup); | 757 __ bind(&miss_cleanup); |
| 763 FreeSpaceForFastApiCall(masm, scratch1); | 758 FreeSpaceForFastApiCall(masm, scratch1); |
| 764 __ jmp(miss_label); | 759 __ jmp(miss_label); |
| 765 } | 760 } |
| 766 | 761 |
| 767 // Invoke a regular function. | 762 // Invoke a regular function. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 | 810 |
| 816 __ pop(name_); // Restore the name. | 811 __ pop(name_); // Restore the name. |
| 817 __ pop(receiver); // Restore the holder. | 812 __ pop(receiver); // Restore the holder. |
| 818 // Leave the internal frame. | 813 // Leave the internal frame. |
| 819 } | 814 } |
| 820 | 815 |
| 821 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 816 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 822 __ j(not_equal, interceptor_succeeded); | 817 __ j(not_equal, interceptor_succeeded); |
| 823 } | 818 } |
| 824 | 819 |
| 825 StubCompiler* stub_compiler_; | 820 CallStubCompiler* stub_compiler_; |
| 826 const ParameterCount& arguments_; | 821 const ParameterCount& arguments_; |
| 827 Register name_; | 822 Register name_; |
| 828 ExtraICState extra_ic_state_; | 823 ExtraICState extra_ic_state_; |
| 829 }; | 824 }; |
| 830 | 825 |
| 831 | 826 |
| 832 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 827 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 833 Label* label, | 828 Label* label, |
| 834 Handle<Name> name) { | 829 Handle<Name> name) { |
| 835 if (!label->is_unused()) { | 830 if (!label->is_unused()) { |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 | 1525 |
| 1531 | 1526 |
| 1532 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1527 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1533 if (kind_ == Code::KEYED_CALL_IC) { | 1528 if (kind_ == Code::KEYED_CALL_IC) { |
| 1534 __ Cmp(rcx, name); | 1529 __ Cmp(rcx, name); |
| 1535 __ j(not_equal, miss); | 1530 __ j(not_equal, miss); |
| 1536 } | 1531 } |
| 1537 } | 1532 } |
| 1538 | 1533 |
| 1539 | 1534 |
| 1535 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1536 Register scratch, |
| 1537 Label* miss) { |
| 1538 __ JumpIfSmi(function, miss); |
| 1539 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 1540 __ j(not_equal, miss); |
| 1541 } |
| 1542 |
| 1543 |
| 1540 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1544 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1541 Handle<Cell> cell, | 1545 Handle<Cell> cell, |
| 1542 Handle<JSFunction> function, | 1546 Handle<JSFunction> function, |
| 1543 Label* miss) { | 1547 Label* miss) { |
| 1544 // Get the value from the cell. | 1548 // Get the value from the cell. |
| 1545 __ Move(rdi, cell); | 1549 __ Move(rdi, cell); |
| 1546 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1550 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| 1547 | 1551 |
| 1548 // Check that the cell contains the same function. | 1552 // Check that the cell contains the same function. |
| 1549 if (heap()->InNewSpace(*function)) { | 1553 if (heap()->InNewSpace(*function)) { |
| 1550 // We can't embed a pointer to a function in new space so we have | 1554 // We can't embed a pointer to a function in new space so we have |
| 1551 // to verify that the shared function info is unchanged. This has | 1555 // to verify that the shared function info is unchanged. This has |
| 1552 // the nice side effect that multiple closures based on the same | 1556 // the nice side effect that multiple closures based on the same |
| 1553 // function can all use this call IC. Before we load through the | 1557 // function can all use this call IC. Before we load through the |
| 1554 // function, we have to verify that it still is a function. | 1558 // function, we have to verify that it still is a function. |
| 1555 __ JumpIfSmi(rdi, miss); | 1559 GenerateFunctionCheck(rdi, rax, miss); |
| 1556 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | |
| 1557 __ j(not_equal, miss); | |
| 1558 | 1560 |
| 1559 // Check the shared function info. Make sure it hasn't changed. | 1561 // Check the shared function info. Make sure it hasn't changed. |
| 1560 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1562 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1561 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1563 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1562 } else { | 1564 } else { |
| 1563 __ Cmp(rdi, function); | 1565 __ Cmp(rdi, function); |
| 1564 } | 1566 } |
| 1565 __ j(not_equal, miss); | 1567 __ j(not_equal, miss); |
| 1566 } | 1568 } |
| 1567 | 1569 |
| 1568 | 1570 |
| 1569 void CallStubCompiler::GenerateMissBranch() { | 1571 void CallStubCompiler::GenerateMissBranch() { |
| 1570 Handle<Code> code = | 1572 Handle<Code> code = |
| 1571 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1573 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1572 kind_, | 1574 kind_, |
| 1573 extra_state_); | 1575 extra_state()); |
| 1574 __ Jump(code, RelocInfo::CODE_TARGET); | 1576 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1575 } | 1577 } |
| 1576 | 1578 |
| 1577 | 1579 |
| 1578 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1580 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1579 Handle<JSObject> holder, | 1581 Handle<JSObject> holder, |
| 1580 PropertyIndex index, | 1582 PropertyIndex index, |
| 1581 Handle<Name> name) { | 1583 Handle<Name> name) { |
| 1582 Label miss; | 1584 Label miss; |
| 1583 | 1585 |
| 1584 Register reg = HandlerFrontendHeader( | 1586 Register reg = HandlerFrontendHeader( |
| 1585 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1587 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1586 | 1588 |
| 1587 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1589 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1588 index.translate(holder), Representation::Tagged()); | 1590 index.translate(holder), Representation::Tagged()); |
| 1589 | 1591 GenerateJumpFunction(object, rdi, &miss); |
| 1590 // Check that the function really is a function. | |
| 1591 __ JumpIfSmi(rdi, &miss); | |
| 1592 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | |
| 1593 __ j(not_equal, &miss); | |
| 1594 | |
| 1595 PatchGlobalProxy(object); | |
| 1596 | |
| 1597 // Invoke the function. | |
| 1598 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 1599 ? CALL_AS_FUNCTION | |
| 1600 : CALL_AS_METHOD; | |
| 1601 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 1602 NullCallWrapper(), call_kind); | |
| 1603 | 1592 |
| 1604 HandlerFrontendFooter(&miss); | 1593 HandlerFrontendFooter(&miss); |
| 1605 | 1594 |
| 1606 // Return the generated code. | 1595 // Return the generated code. |
| 1607 return GetCode(Code::FAST, name); | 1596 return GetCode(Code::FAST, name); |
| 1608 } | 1597 } |
| 1609 | 1598 |
| 1610 | 1599 |
| 1611 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1600 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1612 Handle<Object> object, | 1601 Handle<Object> object, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1641 } | 1630 } |
| 1642 | 1631 |
| 1643 | 1632 |
| 1644 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1633 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1645 Handle<Object> object, | 1634 Handle<Object> object, |
| 1646 Handle<JSObject> holder, | 1635 Handle<JSObject> holder, |
| 1647 Handle<Cell> cell, | 1636 Handle<Cell> cell, |
| 1648 Handle<JSFunction> function, | 1637 Handle<JSFunction> function, |
| 1649 Handle<String> name, | 1638 Handle<String> name, |
| 1650 Code::StubType type) { | 1639 Code::StubType type) { |
| 1651 // ----------- S t a t e ------------- | 1640 // If object is not an array or is observed or sealed, bail out to regular |
| 1652 // -- rcx : name | 1641 // call. |
| 1653 // -- rsp[0] : return address | |
| 1654 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 1655 // -- ... | |
| 1656 // -- rsp[(argc + 1) * 8] : receiver | |
| 1657 // ----------------------------------- | |
| 1658 | |
| 1659 // If object is not an array or is observed, bail out to regular call. | |
| 1660 if (!object->IsJSArray() || | 1642 if (!object->IsJSArray() || |
| 1661 !cell.is_null() || | 1643 !cell.is_null() || |
| 1662 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1644 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1645 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1663 return Handle<Code>::null(); | 1646 return Handle<Code>::null(); |
| 1664 } | 1647 } |
| 1665 | 1648 |
| 1666 Label miss; | 1649 Label miss; |
| 1667 | 1650 |
| 1668 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1651 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1669 | 1652 |
| 1670 const int argc = arguments().immediate(); | 1653 const int argc = arguments().immediate(); |
| 1671 StackArgumentsAccessor args(rsp, argc); | 1654 StackArgumentsAccessor args(rsp, argc); |
| 1672 if (argc == 0) { | 1655 if (argc == 0) { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 } | 1871 } |
| 1889 | 1872 |
| 1890 | 1873 |
| 1891 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1874 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1892 Handle<Object> object, | 1875 Handle<Object> object, |
| 1893 Handle<JSObject> holder, | 1876 Handle<JSObject> holder, |
| 1894 Handle<Cell> cell, | 1877 Handle<Cell> cell, |
| 1895 Handle<JSFunction> function, | 1878 Handle<JSFunction> function, |
| 1896 Handle<String> name, | 1879 Handle<String> name, |
| 1897 Code::StubType type) { | 1880 Code::StubType type) { |
| 1898 // If object is not an array or is observed, bail out to regular call. | 1881 // If object is not an array or is observed or sealed, bail out to regular |
| 1882 // call. |
| 1899 if (!object->IsJSArray() || | 1883 if (!object->IsJSArray() || |
| 1900 !cell.is_null() || | 1884 !cell.is_null() || |
| 1901 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1885 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1886 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1902 return Handle<Code>::null(); | 1887 return Handle<Code>::null(); |
| 1903 } | 1888 } |
| 1904 | 1889 |
| 1905 Label miss, return_undefined, call_builtin; | 1890 Label miss, return_undefined, call_builtin; |
| 1906 | 1891 |
| 1907 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1892 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1908 | 1893 |
| 1909 // Get the elements array of the object. | 1894 // Get the elements array of the object. |
| 1910 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1895 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 1911 | 1896 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 Handle<String> name, | 1950 Handle<String> name, |
| 1966 Code::StubType type) { | 1951 Code::StubType type) { |
| 1967 // If object is not a string, bail out to regular call. | 1952 // If object is not a string, bail out to regular call. |
| 1968 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1953 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 1969 | 1954 |
| 1970 Label miss; | 1955 Label miss; |
| 1971 Label name_miss; | 1956 Label name_miss; |
| 1972 Label index_out_of_range; | 1957 Label index_out_of_range; |
| 1973 Label* index_out_of_range_label = &index_out_of_range; | 1958 Label* index_out_of_range_label = &index_out_of_range; |
| 1974 if (kind_ == Code::CALL_IC && | 1959 if (kind_ == Code::CALL_IC && |
| 1975 (CallICBase::StringStubState::decode(extra_state_) == | 1960 (CallICBase::StringStubState::decode(extra_state()) == |
| 1976 DEFAULT_STRING_STUB)) { | 1961 DEFAULT_STRING_STUB)) { |
| 1977 index_out_of_range_label = &miss; | 1962 index_out_of_range_label = &miss; |
| 1978 } | 1963 } |
| 1979 | 1964 |
| 1980 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 1965 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 1981 | 1966 |
| 1982 Register receiver = rbx; | 1967 Register receiver = rbx; |
| 1983 Register index = rdi; | 1968 Register index = rdi; |
| 1984 Register result = rax; | 1969 Register result = rax; |
| 1985 const int argc = arguments().immediate(); | 1970 const int argc = arguments().immediate(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2007 | 1992 |
| 2008 if (index_out_of_range.is_linked()) { | 1993 if (index_out_of_range.is_linked()) { |
| 2009 __ bind(&index_out_of_range); | 1994 __ bind(&index_out_of_range); |
| 2010 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 1995 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 2011 __ ret((argc + 1) * kPointerSize); | 1996 __ ret((argc + 1) * kPointerSize); |
| 2012 } | 1997 } |
| 2013 | 1998 |
| 2014 __ bind(&miss); | 1999 __ bind(&miss); |
| 2015 // Restore function name in rcx. | 2000 // Restore function name in rcx. |
| 2016 __ Move(rcx, name); | 2001 __ Move(rcx, name); |
| 2017 __ bind(&name_miss); | 2002 HandlerFrontendFooter(&name_miss); |
| 2018 GenerateMissBranch(); | |
| 2019 | 2003 |
| 2020 // Return the generated code. | 2004 // Return the generated code. |
| 2021 return GetCode(type, name); | 2005 return GetCode(type, name); |
| 2022 } | 2006 } |
| 2023 | 2007 |
| 2024 | 2008 |
| 2025 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2009 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2026 Handle<Object> object, | 2010 Handle<Object> object, |
| 2027 Handle<JSObject> holder, | 2011 Handle<JSObject> holder, |
| 2028 Handle<Cell> cell, | 2012 Handle<Cell> cell, |
| 2029 Handle<JSFunction> function, | 2013 Handle<JSFunction> function, |
| 2030 Handle<String> name, | 2014 Handle<String> name, |
| 2031 Code::StubType type) { | 2015 Code::StubType type) { |
| 2032 // If object is not a string, bail out to regular call. | 2016 // If object is not a string, bail out to regular call. |
| 2033 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2017 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2034 | 2018 |
| 2035 const int argc = arguments().immediate(); | 2019 const int argc = arguments().immediate(); |
| 2036 StackArgumentsAccessor args(rsp, argc); | 2020 StackArgumentsAccessor args(rsp, argc); |
| 2037 | 2021 |
| 2038 Label miss; | 2022 Label miss; |
| 2039 Label name_miss; | 2023 Label name_miss; |
| 2040 Label index_out_of_range; | 2024 Label index_out_of_range; |
| 2041 Label* index_out_of_range_label = &index_out_of_range; | 2025 Label* index_out_of_range_label = &index_out_of_range; |
| 2042 if (kind_ == Code::CALL_IC && | 2026 if (kind_ == Code::CALL_IC && |
| 2043 (CallICBase::StringStubState::decode(extra_state_) == | 2027 (CallICBase::StringStubState::decode(extra_state()) == |
| 2044 DEFAULT_STRING_STUB)) { | 2028 DEFAULT_STRING_STUB)) { |
| 2045 index_out_of_range_label = &miss; | 2029 index_out_of_range_label = &miss; |
| 2046 } | 2030 } |
| 2047 | 2031 |
| 2048 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 2032 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2049 | 2033 |
| 2050 Register receiver = rax; | 2034 Register receiver = rax; |
| 2051 Register index = rdi; | 2035 Register index = rdi; |
| 2052 Register scratch = rdx; | 2036 Register scratch = rdx; |
| 2053 Register result = rax; | 2037 Register result = rax; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2073 generator.GenerateSlow(masm(), call_helper); | 2057 generator.GenerateSlow(masm(), call_helper); |
| 2074 | 2058 |
| 2075 if (index_out_of_range.is_linked()) { | 2059 if (index_out_of_range.is_linked()) { |
| 2076 __ bind(&index_out_of_range); | 2060 __ bind(&index_out_of_range); |
| 2077 __ LoadRoot(rax, Heap::kempty_stringRootIndex); | 2061 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
| 2078 __ ret((argc + 1) * kPointerSize); | 2062 __ ret((argc + 1) * kPointerSize); |
| 2079 } | 2063 } |
| 2080 __ bind(&miss); | 2064 __ bind(&miss); |
| 2081 // Restore function name in rcx. | 2065 // Restore function name in rcx. |
| 2082 __ Move(rcx, name); | 2066 __ Move(rcx, name); |
| 2083 __ bind(&name_miss); | 2067 HandlerFrontendFooter(&name_miss); |
| 2084 GenerateMissBranch(); | |
| 2085 | 2068 |
| 2086 // Return the generated code. | 2069 // Return the generated code. |
| 2087 return GetCode(type, name); | 2070 return GetCode(type, name); |
| 2088 } | 2071 } |
| 2089 | 2072 |
| 2090 | 2073 |
| 2091 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2074 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2092 Handle<Object> object, | 2075 Handle<Object> object, |
| 2093 Handle<JSObject> holder, | 2076 Handle<JSObject> holder, |
| 2094 Handle<Cell> cell, | 2077 Handle<Cell> cell, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2120 // Convert the smi code to uint16. | 2103 // Convert the smi code to uint16. |
| 2121 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2104 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2122 | 2105 |
| 2123 StringCharFromCodeGenerator generator(code, rax); | 2106 StringCharFromCodeGenerator generator(code, rax); |
| 2124 generator.GenerateFast(masm()); | 2107 generator.GenerateFast(masm()); |
| 2125 __ ret(2 * kPointerSize); | 2108 __ ret(2 * kPointerSize); |
| 2126 | 2109 |
| 2127 StubRuntimeCallHelper call_helper; | 2110 StubRuntimeCallHelper call_helper; |
| 2128 generator.GenerateSlow(masm(), call_helper); | 2111 generator.GenerateSlow(masm(), call_helper); |
| 2129 | 2112 |
| 2130 // Tail call the full function. We do not have to patch the receiver | |
| 2131 // because the function makes no use of it. | |
| 2132 __ bind(&slow); | 2113 __ bind(&slow); |
| 2133 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2114 // We do not have to patch the receiver because the function makes no use of |
| 2134 ? CALL_AS_FUNCTION | 2115 // it. |
| 2135 : CALL_AS_METHOD; | 2116 GenerateJumpFunctionIgnoreReceiver(function); |
| 2136 ParameterCount expected(function); | |
| 2137 __ InvokeFunction(function, expected, arguments(), | |
| 2138 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2139 | 2117 |
| 2140 HandlerFrontendFooter(&miss); | 2118 HandlerFrontendFooter(&miss); |
| 2141 | 2119 |
| 2142 // Return the generated code. | 2120 // Return the generated code. |
| 2143 return GetCode(type, name); | 2121 return GetCode(type, name); |
| 2144 } | 2122 } |
| 2145 | 2123 |
| 2146 | 2124 |
| 2147 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2125 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2148 Handle<Object> object, | 2126 Handle<Object> object, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 // Return a new heap number. | 2209 // Return a new heap number. |
| 2232 __ AllocateHeapNumber(rax, rbx, &slow); | 2210 __ AllocateHeapNumber(rax, rbx, &slow); |
| 2233 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 2211 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 2234 __ ret(2 * kPointerSize); | 2212 __ ret(2 * kPointerSize); |
| 2235 | 2213 |
| 2236 // Return the argument (when it's an already round heap number). | 2214 // Return the argument (when it's an already round heap number). |
| 2237 __ bind(&already_round); | 2215 __ bind(&already_round); |
| 2238 __ movq(rax, args.GetArgumentOperand(1)); | 2216 __ movq(rax, args.GetArgumentOperand(1)); |
| 2239 __ ret(2 * kPointerSize); | 2217 __ ret(2 * kPointerSize); |
| 2240 | 2218 |
| 2241 // Tail call the full function. We do not have to patch the receiver | |
| 2242 // because the function makes no use of it. | |
| 2243 __ bind(&slow); | 2219 __ bind(&slow); |
| 2244 ParameterCount expected(function); | 2220 // We do not have to patch the receiver because the function makes no use of |
| 2245 __ InvokeFunction(function, expected, arguments(), | 2221 // it. |
| 2246 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2222 GenerateJumpFunctionIgnoreReceiver(function); |
| 2247 | 2223 |
| 2248 HandlerFrontendFooter(&miss); | 2224 HandlerFrontendFooter(&miss); |
| 2249 | 2225 |
| 2250 // Return the generated code. | 2226 // Return the generated code. |
| 2251 return GetCode(type, name); | 2227 return GetCode(type, name); |
| 2252 } | 2228 } |
| 2253 | 2229 |
| 2254 | 2230 |
| 2255 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2231 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2256 Handle<Object> object, | 2232 Handle<Object> object, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2317 __ ret(2 * kPointerSize); | 2293 __ ret(2 * kPointerSize); |
| 2318 | 2294 |
| 2319 // If the argument is negative, clear the sign, and return a new | 2295 // If the argument is negative, clear the sign, and return a new |
| 2320 // number. We still have the sign mask in rdi. | 2296 // number. We still have the sign mask in rdi. |
| 2321 __ bind(&negative_sign); | 2297 __ bind(&negative_sign); |
| 2322 __ xor_(rbx, rdi); | 2298 __ xor_(rbx, rdi); |
| 2323 __ AllocateHeapNumber(rax, rdx, &slow); | 2299 __ AllocateHeapNumber(rax, rdx, &slow); |
| 2324 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2300 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 2325 __ ret(2 * kPointerSize); | 2301 __ ret(2 * kPointerSize); |
| 2326 | 2302 |
| 2327 // Tail call the full function. We do not have to patch the receiver | |
| 2328 // because the function makes no use of it. | |
| 2329 __ bind(&slow); | 2303 __ bind(&slow); |
| 2330 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2304 // We do not have to patch the receiver because the function makes no use of |
| 2331 ? CALL_AS_FUNCTION | 2305 // it. |
| 2332 : CALL_AS_METHOD; | 2306 GenerateJumpFunctionIgnoreReceiver(function); |
| 2333 ParameterCount expected(function); | |
| 2334 __ InvokeFunction(function, expected, arguments(), | |
| 2335 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2336 | 2307 |
| 2337 HandlerFrontendFooter(&miss); | 2308 HandlerFrontendFooter(&miss); |
| 2338 | 2309 |
| 2339 // Return the generated code. | 2310 // Return the generated code. |
| 2340 return GetCode(type, name); | 2311 return GetCode(type, name); |
| 2341 } | 2312 } |
| 2342 | 2313 |
| 2343 | 2314 |
| 2344 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2315 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2345 const CallOptimization& optimization, | 2316 const CallOptimization& optimization, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2383 // Move the return address on top of the stack. | 2354 // Move the return address on top of the stack. |
| 2384 __ movq(rax, | 2355 __ movq(rax, |
| 2385 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2356 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
| 2386 __ movq(StackOperandForReturnAddress(0), rax); | 2357 __ movq(StackOperandForReturnAddress(0), rax); |
| 2387 | 2358 |
| 2388 GenerateFastApiCall(masm(), optimization, argc); | 2359 GenerateFastApiCall(masm(), optimization, argc); |
| 2389 | 2360 |
| 2390 __ bind(&miss); | 2361 __ bind(&miss); |
| 2391 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2362 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2392 | 2363 |
| 2393 __ bind(&miss_before_stack_reserved); | 2364 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2394 GenerateMissBranch(); | |
| 2395 | 2365 |
| 2396 // Return the generated code. | 2366 // Return the generated code. |
| 2397 return GetCode(function); | 2367 return GetCode(function); |
| 2398 } | 2368 } |
| 2399 | 2369 |
| 2400 | 2370 |
| 2401 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2371 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2402 Label success; | 2372 Label success; |
| 2403 // Check that the object is a boolean. | 2373 // Check that the object is a boolean. |
| 2404 __ CompareRoot(object, Heap::kTrueValueRootIndex); | 2374 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2492 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2462 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2493 reg = CheckPrototypes( | 2463 reg = CheckPrototypes( |
| 2494 IC::CurrentTypeOf(prototype, isolate()), | 2464 IC::CurrentTypeOf(prototype, isolate()), |
| 2495 rax, holder, rbx, rdx, rdi, name, miss); | 2465 rax, holder, rbx, rdx, rdi, name, miss); |
| 2496 } | 2466 } |
| 2497 | 2467 |
| 2498 return reg; | 2468 return reg; |
| 2499 } | 2469 } |
| 2500 | 2470 |
| 2501 | 2471 |
| 2502 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2472 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2503 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2473 Register function, |
| 2504 ? CALL_AS_FUNCTION | 2474 Label* miss) { |
| 2505 : CALL_AS_METHOD; | 2475 // Check that the function really is a function. |
| 2506 ParameterCount expected(function); | 2476 GenerateFunctionCheck(function, rbx, miss); |
| 2507 __ InvokeFunction(function, expected, arguments(), | 2477 |
| 2508 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2478 if (!function.is(rdi)) __ movq(rdi, function); |
| 2479 PatchGlobalProxy(object); |
| 2480 |
| 2481 // Invoke the function. |
| 2482 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2483 NullCallWrapper(), call_kind()); |
| 2509 } | 2484 } |
| 2510 | 2485 |
| 2511 | 2486 |
| 2512 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2513 Handle<Object> object, | |
| 2514 Handle<JSObject> holder, | |
| 2515 Handle<Name> name, | |
| 2516 CheckType check, | |
| 2517 Handle<JSFunction> function) { | |
| 2518 if (HasCustomCallGenerator(function)) { | |
| 2519 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2520 Handle<PropertyCell>::null(), | |
| 2521 function, Handle<String>::cast(name), | |
| 2522 Code::FAST); | |
| 2523 // A null handle means bail out to the regular compiler code below. | |
| 2524 if (!code.is_null()) return code; | |
| 2525 } | |
| 2526 | |
| 2527 Label miss; | |
| 2528 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2529 PatchGlobalProxy(object); | |
| 2530 CompileHandlerBackend(function); | |
| 2531 HandlerFrontendFooter(&miss); | |
| 2532 | |
| 2533 // Return the generated code. | |
| 2534 return GetCode(function); | |
| 2535 } | |
| 2536 | |
| 2537 | |
| 2538 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2487 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2539 Handle<JSObject> holder, | 2488 Handle<JSObject> holder, |
| 2540 Handle<Name> name) { | 2489 Handle<Name> name) { |
| 2541 Label miss; | 2490 Label miss; |
| 2542 GenerateNameCheck(name, &miss); | 2491 GenerateNameCheck(name, &miss); |
| 2543 | 2492 |
| 2544 LookupResult lookup(isolate()); | 2493 LookupResult lookup(isolate()); |
| 2545 LookupPostInterceptor(holder, name, &lookup); | 2494 LookupPostInterceptor(holder, name, &lookup); |
| 2546 | 2495 |
| 2547 // Get the receiver from the stack. | 2496 // Get the receiver from the stack. |
| 2548 StackArgumentsAccessor args(rsp, arguments()); | 2497 StackArgumentsAccessor args(rsp, arguments()); |
| 2549 __ movq(rdx, args.GetReceiverOperand()); | 2498 __ movq(rdx, args.GetReceiverOperand()); |
| 2550 | 2499 |
| 2551 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2500 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state()); |
| 2552 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2501 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2553 &miss); | 2502 &miss); |
| 2554 | 2503 |
| 2555 // Restore receiver. | 2504 // Restore receiver. |
| 2556 __ movq(rdx, args.GetReceiverOperand()); | 2505 __ movq(rdx, args.GetReceiverOperand()); |
| 2557 | 2506 |
| 2558 // Check that the function really is a function. | 2507 GenerateJumpFunction(object, rax, &miss); |
| 2559 __ JumpIfSmi(rax, &miss); | |
| 2560 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | |
| 2561 __ j(not_equal, &miss); | |
| 2562 | 2508 |
| 2563 // Patch the receiver on the stack with the global proxy if | 2509 HandlerFrontendFooter(&miss); |
| 2564 // necessary. | |
| 2565 if (object->IsGlobalObject()) { | |
| 2566 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2567 __ movq(args.GetReceiverOperand(), rdx); | |
| 2568 } | |
| 2569 | |
| 2570 // Invoke the function. | |
| 2571 __ movq(rdi, rax); | |
| 2572 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2573 ? CALL_AS_FUNCTION | |
| 2574 : CALL_AS_METHOD; | |
| 2575 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 2576 NullCallWrapper(), call_kind); | |
| 2577 | |
| 2578 // Handle load cache miss. | |
| 2579 __ bind(&miss); | |
| 2580 GenerateMissBranch(); | |
| 2581 | 2510 |
| 2582 // Return the generated code. | 2511 // Return the generated code. |
| 2583 return GetCode(Code::FAST, name); | 2512 return GetCode(Code::FAST, name); |
| 2584 } | 2513 } |
| 2585 | 2514 |
| 2586 | 2515 |
| 2587 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2516 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2588 Handle<JSObject> object, | 2517 Handle<JSObject> object, |
| 2589 Handle<GlobalObject> holder, | 2518 Handle<GlobalObject> holder, |
| 2590 Handle<PropertyCell> cell, | 2519 Handle<PropertyCell> cell, |
| 2591 Handle<JSFunction> function, | 2520 Handle<JSFunction> function, |
| 2592 Handle<Name> name) { | 2521 Handle<Name> name) { |
| 2593 if (HasCustomCallGenerator(function)) { | 2522 if (HasCustomCallGenerator(function)) { |
| 2594 Handle<Code> code = CompileCustomCall( | 2523 Handle<Code> code = CompileCustomCall( |
| 2595 object, holder, cell, function, Handle<String>::cast(name), | 2524 object, holder, cell, function, Handle<String>::cast(name), |
| 2596 Code::NORMAL); | 2525 Code::NORMAL); |
| 2597 // A null handle means bail out to the regular compiler code below. | 2526 // A null handle means bail out to the regular compiler code below. |
| 2598 if (!code.is_null()) return code; | 2527 if (!code.is_null()) return code; |
| 2599 } | 2528 } |
| 2600 | 2529 |
| 2601 Label miss; | 2530 Label miss; |
| 2602 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2531 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2532 // Potentially loads a closure that matches the shared function info of the |
| 2533 // function, rather than function. |
| 2603 GenerateLoadFunctionFromCell(cell, function, &miss); | 2534 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2604 PatchGlobalProxy(object); | |
| 2605 | |
| 2606 // Set up the context (function already in rdi). | |
| 2607 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 2608 | |
| 2609 // Jump to the cached code (tail call). | |
| 2610 Counters* counters = isolate()->counters(); | 2535 Counters* counters = isolate()->counters(); |
| 2611 __ IncrementCounter(counters->call_global_inline(), 1); | 2536 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2612 ParameterCount expected(function->shared()->formal_parameter_count()); | 2537 GenerateJumpFunction(object, rdi, function); |
| 2613 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2614 ? CALL_AS_FUNCTION | |
| 2615 : CALL_AS_METHOD; | |
| 2616 // We call indirectly through the code field in the function to | |
| 2617 // allow recompilation to take effect without changing any of the | |
| 2618 // call sites. | |
| 2619 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | |
| 2620 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | |
| 2621 NullCallWrapper(), call_kind); | |
| 2622 | |
| 2623 HandlerFrontendFooter(&miss); | 2538 HandlerFrontendFooter(&miss); |
| 2624 | 2539 |
| 2625 // Return the generated code. | 2540 // Return the generated code. |
| 2626 return GetCode(Code::NORMAL, name); | 2541 return GetCode(Code::NORMAL, name); |
| 2627 } | 2542 } |
| 2628 | 2543 |
| 2629 | 2544 |
| 2630 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2545 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2631 Handle<JSObject> object, | 2546 Handle<JSObject> object, |
| 2632 Handle<JSObject> holder, | 2547 Handle<JSObject> holder, |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2996 // ----------------------------------- | 2911 // ----------------------------------- |
| 2997 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2912 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2998 } | 2913 } |
| 2999 | 2914 |
| 3000 | 2915 |
| 3001 #undef __ | 2916 #undef __ |
| 3002 | 2917 |
| 3003 } } // namespace v8::internal | 2918 } } // namespace v8::internal |
| 3004 | 2919 |
| 3005 #endif // V8_TARGET_ARCH_X64 | 2920 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |