| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 697 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 698 Label* label, | 698 Label* label, |
| 699 Handle<Name> name) { | 699 Handle<Name> name) { |
| 700 if (!label->is_unused()) { | 700 if (!label->is_unused()) { |
| 701 __ Bind(label); | 701 __ Bind(label); |
| 702 __ Mov(this->name(), Operand(name)); | 702 __ Mov(this->name(), Operand(name)); |
| 703 } | 703 } |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 // The function to called must be passed in x1. | |
| 708 static void GenerateCallFunction(MacroAssembler* masm, | |
| 709 Handle<Object> object, | |
| 710 const ParameterCount& arguments, | |
| 711 Label* miss, | |
| 712 ExtraICState extra_ic_state, | |
| 713 Register function, | |
| 714 Register receiver, | |
| 715 Register scratch) { | |
| 716 ASSERT(!AreAliased(function, receiver, scratch)); | |
| 717 ASSERT(function.Is(x1)); | |
| 718 | |
| 719 // Check that the function really is a function. | |
| 720 __ JumpIfSmi(function, miss); | |
| 721 __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss); | |
| 722 | |
| 723 if (object->IsGlobalObject()) { | |
| 724 const int argc = arguments.immediate(); | |
| 725 const int receiver_offset = argc * kPointerSize; | |
| 726 __ Ldr(scratch, | |
| 727 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | |
| 728 __ Poke(scratch, receiver_offset); | |
| 729 } | |
| 730 | |
| 731 // Invoke the function. | |
| 732 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | |
| 733 ? CALL_AS_FUNCTION | |
| 734 : CALL_AS_METHOD; | |
| 735 __ InvokeFunction( | |
| 736 function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 737 } | |
| 738 | |
| 739 | |
| 740 static void PushInterceptorArguments(MacroAssembler* masm, | 707 static void PushInterceptorArguments(MacroAssembler* masm, |
| 741 Register receiver, | 708 Register receiver, |
| 742 Register holder, | 709 Register holder, |
| 743 Register name, | 710 Register name, |
| 744 Handle<JSObject> holder_obj) { | 711 Handle<JSObject> holder_obj) { |
| 745 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 712 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 746 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 713 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 747 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 714 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 748 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 715 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 749 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 716 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 ASSERT(!AreAliased(receiver, scratch, values[i])); | 898 ASSERT(!AreAliased(receiver, scratch, values[i])); |
| 932 __ Poke(receiver, index-- * kPointerSize); | 899 __ Poke(receiver, index-- * kPointerSize); |
| 933 } | 900 } |
| 934 | 901 |
| 935 GenerateFastApiDirectCall(masm, optimization, argc, true); | 902 GenerateFastApiDirectCall(masm, optimization, argc, true); |
| 936 } | 903 } |
| 937 | 904 |
| 938 | 905 |
| 939 class CallInterceptorCompiler BASE_EMBEDDED { | 906 class CallInterceptorCompiler BASE_EMBEDDED { |
| 940 public: | 907 public: |
| 941 CallInterceptorCompiler(StubCompiler* stub_compiler, | 908 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 942 const ParameterCount& arguments, | 909 const ParameterCount& arguments, |
| 943 Register name, | 910 Register name, |
| 944 ExtraICState extra_ic_state) | 911 ExtraICState extra_ic_state) |
| 945 : stub_compiler_(stub_compiler), | 912 : stub_compiler_(stub_compiler), |
| 946 arguments_(arguments), | 913 arguments_(arguments), |
| 947 name_(name), | 914 name_(name), |
| 948 extra_ic_state_(extra_ic_state) {} | 915 extra_ic_state_(extra_ic_state) {} |
| 949 | 916 |
| 950 void Compile(MacroAssembler* masm, | 917 void Compile(MacroAssembler* masm, |
| 951 Handle<JSObject> object, | 918 Handle<JSObject> object, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 // safe to omit it here, as if present, it should be fetched | 1013 // safe to omit it here, as if present, it should be fetched |
| 1047 // by the previous CheckPrototypes. | 1014 // by the previous CheckPrototypes. |
| 1048 ASSERT(depth2 == kInvalidProtoDepth); | 1015 ASSERT(depth2 == kInvalidProtoDepth); |
| 1049 } | 1016 } |
| 1050 | 1017 |
| 1051 // Invoke function. | 1018 // Invoke function. |
| 1052 if (can_do_fast_api_call) { | 1019 if (can_do_fast_api_call) { |
| 1053 GenerateFastApiDirectCall( | 1020 GenerateFastApiDirectCall( |
| 1054 masm, optimization, arguments_.immediate(), false); | 1021 masm, optimization, arguments_.immediate(), false); |
| 1055 } else { | 1022 } else { |
| 1056 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 1057 ? CALL_AS_FUNCTION | |
| 1058 : CALL_AS_METHOD; | |
| 1059 Handle<JSFunction> function = optimization.constant_function(); | 1023 Handle<JSFunction> function = optimization.constant_function(); |
| 1060 ParameterCount expected(function); | 1024 stub_compiler_->GenerateJumpFunctionIgnoreReceiver(function); |
| 1061 __ InvokeFunction(function, expected, arguments_, | |
| 1062 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 1063 } | 1025 } |
| 1064 | 1026 |
| 1065 // Deferred code for fast API call case, clean preallocated space. | 1027 // Deferred code for fast API call case, clean preallocated space. |
| 1066 if (can_do_fast_api_call) { | 1028 if (can_do_fast_api_call) { |
| 1067 __ Bind(&miss_cleanup); | 1029 __ Bind(&miss_cleanup); |
| 1068 FreeSpaceForFastApiCall(masm); | 1030 FreeSpaceForFastApiCall(masm); |
| 1069 __ B(miss_label); | 1031 __ B(miss_label); |
| 1070 } | 1032 } |
| 1071 | 1033 |
| 1072 // Invoke a regular function. | 1034 // Invoke a regular function. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 IC::kLoadPropertyWithInterceptorOnly); | 1079 IC::kLoadPropertyWithInterceptorOnly); |
| 1118 __ Pop(name_, receiver); | 1080 __ Pop(name_, receiver); |
| 1119 } | 1081 } |
| 1120 | 1082 |
| 1121 // If interceptor returns no-result sentinel, call the constant function. | 1083 // If interceptor returns no-result sentinel, call the constant function. |
| 1122 __ JumpIfNotRoot(x0, | 1084 __ JumpIfNotRoot(x0, |
| 1123 Heap::kNoInterceptorResultSentinelRootIndex, | 1085 Heap::kNoInterceptorResultSentinelRootIndex, |
| 1124 interceptor_succeeded); | 1086 interceptor_succeeded); |
| 1125 } | 1087 } |
| 1126 | 1088 |
| 1127 StubCompiler* stub_compiler_; | 1089 CallStubCompiler* stub_compiler_; |
| 1128 const ParameterCount& arguments_; | 1090 const ParameterCount& arguments_; |
| 1129 Register name_; | 1091 Register name_; |
| 1130 ExtraICState extra_ic_state_; | 1092 ExtraICState extra_ic_state_; |
| 1131 }; | 1093 }; |
| 1132 | 1094 |
| 1133 | 1095 |
| 1134 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1096 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1135 __ Jump(code, RelocInfo::CODE_TARGET); | 1097 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1136 } | 1098 } |
| 1137 | 1099 |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1524 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1563 Register name_reg = x2; | 1525 Register name_reg = x2; |
| 1564 | 1526 |
| 1565 if (kind_ == Code::KEYED_CALL_IC) { | 1527 if (kind_ == Code::KEYED_CALL_IC) { |
| 1566 __ Cmp(name_reg, Operand(name)); | 1528 __ Cmp(name_reg, Operand(name)); |
| 1567 __ B(ne, miss); | 1529 __ B(ne, miss); |
| 1568 } | 1530 } |
| 1569 } | 1531 } |
| 1570 | 1532 |
| 1571 | 1533 |
| 1534 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1535 Register scratch, |
| 1536 Label* miss) { |
| 1537 __ JumpIfSmi(function, miss); |
| 1538 __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss); |
| 1539 } |
| 1540 |
| 1541 |
| 1572 // Load the function object into x1 register. | 1542 // Load the function object into x1 register. |
| 1573 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1543 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1574 Handle<Cell> cell, | 1544 Handle<Cell> cell, |
| 1575 Handle<JSFunction> function, | 1545 Handle<JSFunction> function, |
| 1576 Label* miss) { | 1546 Label* miss) { |
| 1577 // Get the value from the cell. | 1547 // Get the value from the cell. |
| 1578 __ Mov(x3, Operand(cell)); | 1548 __ Mov(x3, Operand(cell)); |
| 1579 Register function_reg = x1; | 1549 Register function_reg = x1; |
| 1580 __ Ldr(function_reg, FieldMemOperand(x3, Cell::kValueOffset)); | 1550 __ Ldr(function_reg, FieldMemOperand(x3, Cell::kValueOffset)); |
| 1581 | 1551 |
| 1582 // Check that the cell contains the same function. | 1552 // Check that the cell contains the same function. |
| 1583 if (heap()->InNewSpace(*function)) { | 1553 if (heap()->InNewSpace(*function)) { |
| 1584 // 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 |
| 1585 // to verify that the shared function info is unchanged. This has | 1555 // to verify that the shared function info is unchanged. This has |
| 1586 // the nice side effect that multiple closures based on the same | 1556 // the nice side effect that multiple closures based on the same |
| 1587 // 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 |
| 1588 // function, we have to verify that it still is a function. | 1558 // function, we have to verify that it still is a function. |
| 1589 __ JumpIfSmi(function_reg, miss); | 1559 GenerateFunctionCheck(function_reg, x3, miss); |
| 1590 __ JumpIfNotObjectType(function_reg, x3, x3, JS_FUNCTION_TYPE, miss); | |
| 1591 | 1560 |
| 1592 // Check the shared function info. Make sure it hasn't changed. | 1561 // Check the shared function info. Make sure it hasn't changed. |
| 1593 __ Mov(x3, Operand(Handle<SharedFunctionInfo>(function->shared()))); | 1562 __ Mov(x3, Operand(Handle<SharedFunctionInfo>(function->shared()))); |
| 1594 __ Ldr(x4, | 1563 __ Ldr(x4, |
| 1595 FieldMemOperand(function_reg, JSFunction::kSharedFunctionInfoOffset)); | 1564 FieldMemOperand(function_reg, JSFunction::kSharedFunctionInfoOffset)); |
| 1596 __ Cmp(x4, x3); | 1565 __ Cmp(x4, x3); |
| 1597 } else { | 1566 } else { |
| 1598 __ Cmp(function_reg, Operand(function)); | 1567 __ Cmp(function_reg, Operand(function)); |
| 1599 } | 1568 } |
| 1600 __ B(ne, miss); | 1569 __ B(ne, miss); |
| 1601 } | 1570 } |
| 1602 | 1571 |
| 1603 | 1572 |
| 1604 void CallStubCompiler::GenerateMissBranch() { | 1573 void CallStubCompiler::GenerateMissBranch() { |
| 1605 Handle<Code> code = | 1574 Handle<Code> code = |
| 1606 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1575 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1607 kind_, | 1576 kind_, |
| 1608 extra_state_); | 1577 extra_state()); |
| 1609 __ Jump(code, RelocInfo::CODE_TARGET); | 1578 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1610 } | 1579 } |
| 1611 | 1580 |
| 1612 | 1581 |
| 1613 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1582 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1614 Handle<JSObject> holder, | 1583 Handle<JSObject> holder, |
| 1615 PropertyIndex index, | 1584 PropertyIndex index, |
| 1616 Handle<Name> name) { | 1585 Handle<Name> name) { |
| 1617 Label miss; | 1586 Label miss; |
| 1618 Register receiver = x0; | |
| 1619 Register function = x1; | 1587 Register function = x1; |
| 1620 | 1588 |
| 1621 Register holder_reg = HandlerFrontendHeader( | 1589 Register holder_reg = HandlerFrontendHeader( |
| 1622 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1590 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1623 | 1591 |
| 1624 GenerateFastPropertyLoad(masm(), function, holder_reg, | 1592 GenerateFastPropertyLoad(masm(), function, holder_reg, |
| 1625 index.is_inobject(holder), | 1593 index.is_inobject(holder), |
| 1626 index.translate(holder), | 1594 index.translate(holder), |
| 1627 Representation::Tagged()); | 1595 Representation::Tagged()); |
| 1628 | 1596 GenerateJumpFunction(object, function, &miss); |
| 1629 GenerateCallFunction( | |
| 1630 masm(), object, arguments(), &miss, extra_state_, function, receiver, x3); | |
| 1631 | 1597 |
| 1632 HandlerFrontendFooter(&miss); | 1598 HandlerFrontendFooter(&miss); |
| 1633 | 1599 |
| 1634 // Return the generated code. | 1600 // Return the generated code. |
| 1635 return GetCode(Code::FAST, name); | 1601 return GetCode(Code::FAST, name); |
| 1636 } | 1602 } |
| 1637 | 1603 |
| 1638 | 1604 |
| 1639 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1605 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1640 Handle<Object> object, | 1606 Handle<Object> object, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1669 } | 1635 } |
| 1670 | 1636 |
| 1671 | 1637 |
| 1672 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1638 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1673 Handle<Object> object, | 1639 Handle<Object> object, |
| 1674 Handle<JSObject> holder, | 1640 Handle<JSObject> holder, |
| 1675 Handle<Cell> cell, | 1641 Handle<Cell> cell, |
| 1676 Handle<JSFunction> function, | 1642 Handle<JSFunction> function, |
| 1677 Handle<String> name, | 1643 Handle<String> name, |
| 1678 Code::StubType type) { | 1644 Code::StubType type) { |
| 1679 // If object is not an array or is observed, bail out to regular call. | 1645 // If object is not an array or is observed or sealed, bail out to regular |
| 1646 // call. |
| 1680 if (!object->IsJSArray() || | 1647 if (!object->IsJSArray() || |
| 1681 !cell.is_null() || | 1648 !cell.is_null() || |
| 1682 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1649 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1650 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1683 return Handle<Code>::null(); | 1651 return Handle<Code>::null(); |
| 1684 } | 1652 } |
| 1685 | 1653 |
| 1686 Label miss; | 1654 Label miss; |
| 1687 | 1655 |
| 1688 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1656 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1689 | 1657 |
| 1690 Register receiver = x0; | 1658 Register receiver = x0; |
| 1691 | 1659 |
| 1692 const int argc = arguments().immediate(); | 1660 const int argc = arguments().immediate(); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 } | 1896 } |
| 1929 | 1897 |
| 1930 | 1898 |
| 1931 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1899 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1932 Handle<Object> object, | 1900 Handle<Object> object, |
| 1933 Handle<JSObject> holder, | 1901 Handle<JSObject> holder, |
| 1934 Handle<Cell> cell, | 1902 Handle<Cell> cell, |
| 1935 Handle<JSFunction> function, | 1903 Handle<JSFunction> function, |
| 1936 Handle<String> name, | 1904 Handle<String> name, |
| 1937 Code::StubType type) { | 1905 Code::StubType type) { |
| 1938 // If object is not an array or is observed, bail out to regular call. | 1906 // If object is not an array or is observed or sealed, bail out to regular |
| 1907 // call. |
| 1939 if (!object->IsJSArray() || | 1908 if (!object->IsJSArray() || |
| 1940 !cell.is_null() || | 1909 !cell.is_null() || |
| 1941 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1910 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1911 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1942 return Handle<Code>::null(); | 1912 return Handle<Code>::null(); |
| 1943 } | 1913 } |
| 1944 | 1914 |
| 1945 const int argc = arguments().immediate(); | 1915 const int argc = arguments().immediate(); |
| 1946 Label miss, return_undefined, call_builtin; | 1916 Label miss, return_undefined, call_builtin; |
| 1947 Register receiver = x0; | 1917 Register receiver = x0; |
| 1948 Register result = x1; | 1918 Register result = x1; |
| 1949 Register elements = x3; | 1919 Register elements = x3; |
| 1950 Register length = x4; | 1920 Register length = x4; |
| 1951 | 1921 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2007 Code::StubType type) { | 1977 Code::StubType type) { |
| 2008 // If object is not a string, bail out to regular call. | 1978 // If object is not a string, bail out to regular call. |
| 2009 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1979 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2010 | 1980 |
| 2011 Label miss; | 1981 Label miss; |
| 2012 Label name_miss; | 1982 Label name_miss; |
| 2013 Label index_out_of_range; | 1983 Label index_out_of_range; |
| 2014 Label* index_out_of_range_label = &index_out_of_range; | 1984 Label* index_out_of_range_label = &index_out_of_range; |
| 2015 | 1985 |
| 2016 if (kind_ == Code::CALL_IC && | 1986 if (kind_ == Code::CALL_IC && |
| 2017 (CallICBase::StringStubState::decode(extra_state_) == | 1987 (CallICBase::StringStubState::decode(extra_state()) == |
| 2018 DEFAULT_STRING_STUB)) { | 1988 DEFAULT_STRING_STUB)) { |
| 2019 index_out_of_range_label = &miss; | 1989 index_out_of_range_label = &miss; |
| 2020 } | 1990 } |
| 2021 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 1991 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2022 | 1992 |
| 2023 Register receiver = x0; | 1993 Register receiver = x0; |
| 2024 Register result = x1; | 1994 Register result = x1; |
| 2025 Register index = x4; | 1995 Register index = x4; |
| 2026 | 1996 |
| 2027 const int argc = arguments().immediate(); | 1997 const int argc = arguments().immediate(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2050 if (index_out_of_range.is_linked()) { | 2020 if (index_out_of_range.is_linked()) { |
| 2051 __ Bind(&index_out_of_range); | 2021 __ Bind(&index_out_of_range); |
| 2052 __ LoadRoot(x0, Heap::kNanValueRootIndex); | 2022 __ LoadRoot(x0, Heap::kNanValueRootIndex); |
| 2053 __ Drop(argc + 1); | 2023 __ Drop(argc + 1); |
| 2054 __ Ret(); | 2024 __ Ret(); |
| 2055 } | 2025 } |
| 2056 | 2026 |
| 2057 __ Bind(&miss); | 2027 __ Bind(&miss); |
| 2058 // Restore function name in x2. | 2028 // Restore function name in x2. |
| 2059 __ Mov(x2, Operand(name)); | 2029 __ Mov(x2, Operand(name)); |
| 2060 __ Bind(&name_miss); | 2030 HandlerFrontendFooter(&name_miss); |
| 2061 GenerateMissBranch(); | |
| 2062 | 2031 |
| 2063 // Return the generated code. | 2032 // Return the generated code. |
| 2064 return GetCode(type, name); | 2033 return GetCode(type, name); |
| 2065 } | 2034 } |
| 2066 | 2035 |
| 2067 | 2036 |
| 2068 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2037 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2069 Handle<Object> object, | 2038 Handle<Object> object, |
| 2070 Handle<JSObject> holder, | 2039 Handle<JSObject> holder, |
| 2071 Handle<Cell> cell, | 2040 Handle<Cell> cell, |
| 2072 Handle<JSFunction> function, | 2041 Handle<JSFunction> function, |
| 2073 Handle<String> name, | 2042 Handle<String> name, |
| 2074 Code::StubType type) { | 2043 Code::StubType type) { |
| 2075 // If object is not a string, bail out to regular call. | 2044 // If object is not a string, bail out to regular call. |
| 2076 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2045 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2077 | 2046 |
| 2078 const int argc = arguments().immediate(); | 2047 const int argc = arguments().immediate(); |
| 2079 Label miss; | 2048 Label miss; |
| 2080 Label name_miss; | 2049 Label name_miss; |
| 2081 Label index_out_of_range; | 2050 Label index_out_of_range; |
| 2082 Label* index_out_of_range_label = &index_out_of_range; | 2051 Label* index_out_of_range_label = &index_out_of_range; |
| 2083 | 2052 |
| 2084 if (kind_ == Code::CALL_IC && | 2053 if (kind_ == Code::CALL_IC && |
| 2085 (CallICBase::StringStubState::decode(extra_state_) == | 2054 (CallICBase::StringStubState::decode(extra_state()) == |
| 2086 DEFAULT_STRING_STUB)) { | 2055 DEFAULT_STRING_STUB)) { |
| 2087 index_out_of_range_label = &miss; | 2056 index_out_of_range_label = &miss; |
| 2088 } | 2057 } |
| 2089 | 2058 |
| 2090 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 2059 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2091 | 2060 |
| 2092 Register receiver = x0; | 2061 Register receiver = x0; |
| 2093 Register index = x4; | 2062 Register index = x4; |
| 2094 Register scratch = x3; | 2063 Register scratch = x3; |
| 2095 Register result = x1; | 2064 Register result = x1; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2119 if (index_out_of_range.is_linked()) { | 2088 if (index_out_of_range.is_linked()) { |
| 2120 __ Bind(&index_out_of_range); | 2089 __ Bind(&index_out_of_range); |
| 2121 __ LoadRoot(x0, Heap::kempty_stringRootIndex); | 2090 __ LoadRoot(x0, Heap::kempty_stringRootIndex); |
| 2122 __ Drop(argc + 1); | 2091 __ Drop(argc + 1); |
| 2123 __ Ret(); | 2092 __ Ret(); |
| 2124 } | 2093 } |
| 2125 | 2094 |
| 2126 __ Bind(&miss); | 2095 __ Bind(&miss); |
| 2127 // Restore function name in x2. | 2096 // Restore function name in x2. |
| 2128 __ Mov(x2, Operand(name)); | 2097 __ Mov(x2, Operand(name)); |
| 2129 __ Bind(&name_miss); | 2098 HandlerFrontendFooter(&name_miss); |
| 2130 GenerateMissBranch(); | |
| 2131 | 2099 |
| 2132 // Return the generated code. | 2100 // Return the generated code. |
| 2133 return GetCode(type, name); | 2101 return GetCode(type, name); |
| 2134 } | 2102 } |
| 2135 | 2103 |
| 2136 | 2104 |
| 2137 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2105 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2138 Handle<Object> object, | 2106 Handle<Object> object, |
| 2139 Handle<JSObject> holder, | 2107 Handle<JSObject> holder, |
| 2140 Handle<Cell> cell, | 2108 Handle<Cell> cell, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2168 | 2136 |
| 2169 Register result = x0; | 2137 Register result = x0; |
| 2170 StringCharFromCodeGenerator generator(code, result); | 2138 StringCharFromCodeGenerator generator(code, result); |
| 2171 generator.GenerateFast(masm()); | 2139 generator.GenerateFast(masm()); |
| 2172 __ Drop(argc + 1); | 2140 __ Drop(argc + 1); |
| 2173 __ Ret(); | 2141 __ Ret(); |
| 2174 | 2142 |
| 2175 StubRuntimeCallHelper call_helper; | 2143 StubRuntimeCallHelper call_helper; |
| 2176 generator.GenerateSlow(masm(), call_helper); | 2144 generator.GenerateSlow(masm(), call_helper); |
| 2177 | 2145 |
| 2178 // Tail call the full function. We do not have to patch the receiver | |
| 2179 // because the function makes no use of it. | |
| 2180 __ Bind(&slow); | 2146 __ Bind(&slow); |
| 2181 ParameterCount expected(function); | 2147 // We do not have to patch the receiver because the function makes no use of |
| 2182 __ InvokeFunction(function, expected, arguments(), | 2148 // it. |
| 2183 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2149 GenerateJumpFunctionIgnoreReceiver(function); |
| 2184 | 2150 |
| 2185 HandlerFrontendFooter(&miss); | 2151 HandlerFrontendFooter(&miss); |
| 2186 | 2152 |
| 2187 // Return the generated code. | 2153 // Return the generated code. |
| 2188 return GetCode(type, name); | 2154 return GetCode(type, name); |
| 2189 } | 2155 } |
| 2190 | 2156 |
| 2191 | 2157 |
| 2192 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2158 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2193 Handle<Object> object, | 2159 Handle<Object> object, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2268 | 2234 |
| 2269 __ Bind(&smi_result); | 2235 __ Bind(&smi_result); |
| 2270 // Tag and return the result. | 2236 // Tag and return the result. |
| 2271 __ SmiTag(result, int_value); | 2237 __ SmiTag(result, int_value); |
| 2272 | 2238 |
| 2273 __ Bind(&return_result); | 2239 __ Bind(&return_result); |
| 2274 __ Drop(argc + 1); | 2240 __ Drop(argc + 1); |
| 2275 __ Ret(); | 2241 __ Ret(); |
| 2276 | 2242 |
| 2277 __ Bind(&slow); | 2243 __ Bind(&slow); |
| 2278 // Tail call the full function. We do not have to patch the receiver | 2244 // We do not have to patch the receiver because the function makes no use of |
| 2279 // because the function makes no use of it. | 2245 // it. |
| 2280 ParameterCount expected(function); | 2246 GenerateJumpFunctionIgnoreReceiver(function); |
| 2281 __ InvokeFunction(function, expected, arguments(), | |
| 2282 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
| 2283 | 2247 |
| 2284 HandlerFrontendFooter(&miss); | 2248 HandlerFrontendFooter(&miss); |
| 2285 | 2249 |
| 2286 // Return the generated code. | 2250 // Return the generated code. |
| 2287 return GetCode(type, name); | 2251 return GetCode(type, name); |
| 2288 } | 2252 } |
| 2289 | 2253 |
| 2290 | 2254 |
| 2291 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2255 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2292 Handle<Object> object, | 2256 Handle<Object> object, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2336 __ Ret(); | 2300 __ Ret(); |
| 2337 | 2301 |
| 2338 __ Bind(&negative_sign); | 2302 __ Bind(&negative_sign); |
| 2339 FPRegister double_value = d0; | 2303 FPRegister double_value = d0; |
| 2340 __ Fmov(double_value, value); | 2304 __ Fmov(double_value, value); |
| 2341 __ Fabs(double_value, double_value); | 2305 __ Fabs(double_value, double_value); |
| 2342 __ AllocateHeapNumberWithValue(result, double_value, &slow, x1, x3); | 2306 __ AllocateHeapNumberWithValue(result, double_value, &slow, x1, x3); |
| 2343 __ Drop(argc + 1); | 2307 __ Drop(argc + 1); |
| 2344 __ Ret(); | 2308 __ Ret(); |
| 2345 | 2309 |
| 2346 // Tail call the full function. We do not have to patch the receiver | |
| 2347 // because the function makes no use of it. | |
| 2348 __ Bind(&slow); | 2310 __ Bind(&slow); |
| 2349 ParameterCount expected(function); | 2311 // We do not have to patch the receiver because the function makes no use of |
| 2350 __ InvokeFunction(function, expected, arguments(), | 2312 // it. |
| 2351 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2313 GenerateJumpFunctionIgnoreReceiver(function); |
| 2352 | 2314 |
| 2353 HandlerFrontendFooter(&miss); | 2315 HandlerFrontendFooter(&miss); |
| 2354 | 2316 |
| 2355 // Return the generated code. | 2317 // Return the generated code. |
| 2356 return GetCode(type, name); | 2318 return GetCode(type, name); |
| 2357 } | 2319 } |
| 2358 | 2320 |
| 2359 | 2321 |
| 2360 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2322 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2361 const CallOptimization& optimization, | 2323 const CallOptimization& optimization, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2395 | 2357 |
| 2396 // Check that the maps haven't changed and find a Holder as a side effect. | 2358 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2397 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), | 2359 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), |
| 2398 receiver, holder, x0, x3, x4, name, depth, &miss); | 2360 receiver, holder, x0, x3, x4, name, depth, &miss); |
| 2399 | 2361 |
| 2400 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2362 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
| 2401 | 2363 |
| 2402 __ Bind(&miss); | 2364 __ Bind(&miss); |
| 2403 FreeSpaceForFastApiCall(masm()); | 2365 FreeSpaceForFastApiCall(masm()); |
| 2404 | 2366 |
| 2405 __ Bind(&miss_before_stack_reserved); | 2367 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2406 GenerateMissBranch(); | |
| 2407 | 2368 |
| 2408 // Return the generated code. | 2369 // Return the generated code. |
| 2409 return GetCode(function); | 2370 return GetCode(function); |
| 2410 } | 2371 } |
| 2411 | 2372 |
| 2412 | 2373 |
| 2413 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2374 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2414 Label success; | 2375 Label success; |
| 2415 // Check that the object is a boolean. | 2376 // Check that the object is a boolean. |
| 2416 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. | 2377 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2510 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2471 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2511 receiver = CheckPrototypes( | 2472 receiver = CheckPrototypes( |
| 2512 IC::CurrentTypeOf(prototype, isolate()), | 2473 IC::CurrentTypeOf(prototype, isolate()), |
| 2513 prototype_reg, holder, x1, x3, x4, name, miss); | 2474 prototype_reg, holder, x1, x3, x4, name, miss); |
| 2514 } | 2475 } |
| 2515 | 2476 |
| 2516 return receiver; | 2477 return receiver; |
| 2517 } | 2478 } |
| 2518 | 2479 |
| 2519 | 2480 |
| 2520 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2481 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2521 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2482 Register function, |
| 2522 ? CALL_AS_FUNCTION | 2483 Label* miss) { |
| 2523 : CALL_AS_METHOD; | 2484 ASSERT(function.Is(x1)); |
| 2524 ParameterCount expected(function); | 2485 // Check that the function really is a function. |
| 2525 __ InvokeFunction(function, expected, arguments(), | 2486 GenerateFunctionCheck(function, x3, miss); |
| 2526 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2487 PatchGlobalProxy(object); |
| 2488 |
| 2489 // Invoke the function. |
| 2490 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2491 NullCallWrapper(), call_kind()); |
| 2527 } | 2492 } |
| 2528 | 2493 |
| 2529 | 2494 |
| 2530 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2531 Handle<Object> object, | |
| 2532 Handle<JSObject> holder, | |
| 2533 Handle<Name> name, | |
| 2534 CheckType check, | |
| 2535 Handle<JSFunction> function) { | |
| 2536 if (HasCustomCallGenerator(function)) { | |
| 2537 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2538 Handle<Cell>::null(), | |
| 2539 function, Handle<String>::cast(name), | |
| 2540 Code::FAST); | |
| 2541 // A null handle means bail out to the regular compiler code below. | |
| 2542 if (!code.is_null()) return code; | |
| 2543 } | |
| 2544 | |
| 2545 Label miss; | |
| 2546 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2547 PatchGlobalProxy(object); | |
| 2548 CompileHandlerBackend(function); | |
| 2549 HandlerFrontendFooter(&miss); | |
| 2550 | |
| 2551 // Return the generated code. | |
| 2552 return GetCode(function); | |
| 2553 } | |
| 2554 | |
| 2555 | |
| 2556 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2495 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2557 Handle<JSObject> holder, | 2496 Handle<JSObject> holder, |
| 2558 Handle<Name> name) { | 2497 Handle<Name> name) { |
| 2559 Label miss; | 2498 Label miss; |
| 2560 Register name_reg = x2; | 2499 Register name_reg = x2; |
| 2561 | 2500 |
| 2562 GenerateNameCheck(name, &miss); | 2501 GenerateNameCheck(name, &miss); |
| 2563 | 2502 |
| 2564 const int argc = arguments().immediate(); | 2503 const int argc = arguments().immediate(); |
| 2565 LookupResult lookup(isolate()); | 2504 LookupResult lookup(isolate()); |
| 2566 LookupPostInterceptor(holder, name, &lookup); | 2505 LookupPostInterceptor(holder, name, &lookup); |
| 2567 | 2506 |
| 2568 // Get the receiver from the stack. | 2507 // Get the receiver from the stack. |
| 2569 Register receiver = x5; | 2508 Register receiver = x5; |
| 2570 __ Peek(receiver, argc * kPointerSize); | 2509 __ Peek(receiver, argc * kPointerSize); |
| 2571 | 2510 |
| 2572 CallInterceptorCompiler compiler(this, arguments(), name_reg, extra_state_); | 2511 CallInterceptorCompiler compiler(this, arguments(), name_reg, extra_state()); |
| 2573 compiler.Compile( | 2512 compiler.Compile( |
| 2574 masm(), object, holder, name, &lookup, receiver, x3, x4, x0, &miss); | 2513 masm(), object, holder, name, &lookup, receiver, x3, x4, x0, &miss); |
| 2575 | 2514 |
| 2576 // Move returned value, the function to call, to x1 (this is required by | 2515 // Move returned value, the function to call, to x1 (this is required by |
| 2577 // GenerateCallFunction). | 2516 // GenerateCallFunction). |
| 2578 Register function = x1; | 2517 Register function = x1; |
| 2579 __ Mov(function, x0); | 2518 __ Mov(function, x0); |
| 2580 | 2519 |
| 2581 // Restore receiver. | 2520 // Restore receiver. |
| 2582 __ Peek(receiver, argc * kPointerSize); | 2521 __ Peek(receiver, argc * kPointerSize); |
| 2583 | 2522 |
| 2584 GenerateCallFunction( | 2523 GenerateJumpFunction(object, x1, &miss); |
| 2585 masm(), object, arguments(), &miss, extra_state_, function, receiver, x3); | |
| 2586 | 2524 |
| 2587 // Handle call cache miss. | 2525 HandlerFrontendFooter(&miss); |
| 2588 __ Bind(&miss); | |
| 2589 GenerateMissBranch(); | |
| 2590 | 2526 |
| 2591 // Return the generated code. | 2527 // Return the generated code. |
| 2592 return GetCode(Code::FAST, name); | 2528 return GetCode(Code::FAST, name); |
| 2593 } | 2529 } |
| 2594 | 2530 |
| 2595 | 2531 |
| 2596 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2532 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2597 Handle<JSObject> object, | 2533 Handle<JSObject> object, |
| 2598 Handle<GlobalObject> holder, | 2534 Handle<GlobalObject> holder, |
| 2599 Handle<PropertyCell> cell, | 2535 Handle<PropertyCell> cell, |
| 2600 Handle<JSFunction> function, | 2536 Handle<JSFunction> function, |
| 2601 Handle<Name> name) { | 2537 Handle<Name> name) { |
| 2602 if (HasCustomCallGenerator(function)) { | 2538 if (HasCustomCallGenerator(function)) { |
| 2603 Handle<Code> code = CompileCustomCall( | 2539 Handle<Code> code = CompileCustomCall( |
| 2604 object, holder, cell, function, Handle<String>::cast(name), | 2540 object, holder, cell, function, Handle<String>::cast(name), |
| 2605 Code::NORMAL); | 2541 Code::NORMAL); |
| 2606 // A null handle means bail out to the regular compiler code below. | 2542 // A null handle means bail out to the regular compiler code below. |
| 2607 if (!code.is_null()) return code; | 2543 if (!code.is_null()) return code; |
| 2608 } | 2544 } |
| 2609 | 2545 |
| 2610 Label miss; | 2546 Label miss; |
| 2611 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2547 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2548 // Potentially loads a closure that matches the shared function info of the |
| 2549 // function, rather than function. |
| 2612 GenerateLoadFunctionFromCell(cell, function, &miss); | 2550 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2613 // After these two calls the receiver is left in x0 and the function in x1. | 2551 // After these two calls the receiver is left in x0 and the function in x1. |
| 2614 Register function_reg = x1; | 2552 Register function_reg = x1; |
| 2615 | 2553 |
| 2616 PatchGlobalProxy(object); | |
| 2617 | |
| 2618 // Set up the context. | |
| 2619 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | |
| 2620 | |
| 2621 // Jump to the cached code (tail call). | |
| 2622 Counters* counters = isolate()->counters(); | 2554 Counters* counters = isolate()->counters(); |
| 2623 __ IncrementCounter(counters->call_global_inline(), 1, x3, x4); | 2555 __ IncrementCounter(counters->call_global_inline(), 1, x3, x4); |
| 2624 ParameterCount expected(function->shared()->formal_parameter_count()); | 2556 GenerateJumpFunction(object, function_reg, function); |
| 2625 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2626 ? CALL_AS_FUNCTION | |
| 2627 : CALL_AS_METHOD; | |
| 2628 // We call indirectly through the code field in the function to | |
| 2629 // allow recompilation to take effect without changing any of the | |
| 2630 // call sites. | |
| 2631 __ Ldr(x3, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | |
| 2632 __ InvokeCode( | |
| 2633 x3, expected, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2634 | |
| 2635 HandlerFrontendFooter(&miss); | 2557 HandlerFrontendFooter(&miss); |
| 2636 | 2558 |
| 2637 // Return the generated code. | 2559 // Return the generated code. |
| 2638 return GetCode(Code::NORMAL, name); | 2560 return GetCode(Code::NORMAL, name); |
| 2639 } | 2561 } |
| 2640 | 2562 |
| 2641 | 2563 |
| 2642 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2564 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2643 Handle<JSObject> object, | 2565 Handle<JSObject> object, |
| 2644 Handle<JSObject> holder, | 2566 Handle<JSObject> holder, |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3006 | 2928 |
| 3007 // Miss case, call the runtime. | 2929 // Miss case, call the runtime. |
| 3008 __ Bind(&miss); | 2930 __ Bind(&miss); |
| 3009 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2931 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3010 } | 2932 } |
| 3011 | 2933 |
| 3012 | 2934 |
| 3013 } } // namespace v8::internal | 2935 } } // namespace v8::internal |
| 3014 | 2936 |
| 3015 #endif // V8_TARGET_ARCH_A64 | 2937 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |