| 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 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 735 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 736 Label* label, | 736 Label* label, |
| 737 Handle<Name> name) { | 737 Handle<Name> name) { |
| 738 if (!label->is_unused()) { | 738 if (!label->is_unused()) { |
| 739 __ bind(label); | 739 __ bind(label); |
| 740 __ mov(this->name(), Operand(name)); | 740 __ mov(this->name(), Operand(name)); |
| 741 } | 741 } |
| 742 } | 742 } |
| 743 | 743 |
| 744 | 744 |
| 745 static void GenerateCallFunction(MacroAssembler* masm, | |
| 746 Handle<Object> object, | |
| 747 const ParameterCount& arguments, | |
| 748 Label* miss, | |
| 749 ExtraICState extra_ic_state) { | |
| 750 // ----------- S t a t e ------------- | |
| 751 // -- r0: receiver | |
| 752 // -- r1: function to call | |
| 753 // ----------------------------------- | |
| 754 | |
| 755 // Check that the function really is a function. | |
| 756 __ JumpIfSmi(r1, miss); | |
| 757 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | |
| 758 __ b(ne, miss); | |
| 759 | |
| 760 if (object->IsGlobalObject()) { | |
| 761 const int argc = arguments.immediate(); | |
| 762 const int receiver_offset = argc * kPointerSize; | |
| 763 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | |
| 764 __ str(r3, MemOperand(sp, receiver_offset)); | |
| 765 } | |
| 766 | |
| 767 // Invoke the function. | |
| 768 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | |
| 769 ? CALL_AS_FUNCTION | |
| 770 : CALL_AS_METHOD; | |
| 771 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 772 } | |
| 773 | |
| 774 | |
| 775 static void PushInterceptorArguments(MacroAssembler* masm, | 745 static void PushInterceptorArguments(MacroAssembler* masm, |
| 776 Register receiver, | 746 Register receiver, |
| 777 Register holder, | 747 Register holder, |
| 778 Register name, | 748 Register name, |
| 779 Handle<JSObject> holder_obj) { | 749 Handle<JSObject> holder_obj) { |
| 780 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 750 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 781 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 751 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 782 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 752 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 783 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 753 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 784 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 754 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 ASSERT(!scratch.is(values[i])); | 918 ASSERT(!scratch.is(values[i])); |
| 949 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); | 919 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); |
| 950 } | 920 } |
| 951 | 921 |
| 952 GenerateFastApiDirectCall(masm, optimization, argc, true); | 922 GenerateFastApiDirectCall(masm, optimization, argc, true); |
| 953 } | 923 } |
| 954 | 924 |
| 955 | 925 |
| 956 class CallInterceptorCompiler BASE_EMBEDDED { | 926 class CallInterceptorCompiler BASE_EMBEDDED { |
| 957 public: | 927 public: |
| 958 CallInterceptorCompiler(StubCompiler* stub_compiler, | 928 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 959 const ParameterCount& arguments, | 929 const ParameterCount& arguments, |
| 960 Register name, | 930 Register name, |
| 961 ExtraICState extra_ic_state) | 931 ExtraICState extra_ic_state) |
| 962 : stub_compiler_(stub_compiler), | 932 : stub_compiler_(stub_compiler), |
| 963 arguments_(arguments), | 933 arguments_(arguments), |
| 964 name_(name), | 934 name_(name), |
| 965 extra_ic_state_(extra_ic_state) {} | 935 extra_ic_state_(extra_ic_state) {} |
| 966 | 936 |
| 967 void Compile(MacroAssembler* masm, | 937 void Compile(MacroAssembler* masm, |
| 968 Handle<JSObject> object, | 938 Handle<JSObject> object, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 // safe to omit it here, as if present, it should be fetched | 1030 // safe to omit it here, as if present, it should be fetched |
| 1061 // by the previous CheckPrototypes. | 1031 // by the previous CheckPrototypes. |
| 1062 ASSERT(depth2 == kInvalidProtoDepth); | 1032 ASSERT(depth2 == kInvalidProtoDepth); |
| 1063 } | 1033 } |
| 1064 | 1034 |
| 1065 // Invoke function. | 1035 // Invoke function. |
| 1066 if (can_do_fast_api_call) { | 1036 if (can_do_fast_api_call) { |
| 1067 GenerateFastApiDirectCall( | 1037 GenerateFastApiDirectCall( |
| 1068 masm, optimization, arguments_.immediate(), false); | 1038 masm, optimization, arguments_.immediate(), false); |
| 1069 } else { | 1039 } else { |
| 1070 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 1071 ? CALL_AS_FUNCTION | |
| 1072 : CALL_AS_METHOD; | |
| 1073 Handle<JSFunction> function = optimization.constant_function(); | 1040 Handle<JSFunction> function = optimization.constant_function(); |
| 1074 ParameterCount expected(function); | 1041 stub_compiler_->GenerateJumpFunctionIgnoreReceiver(function); |
| 1075 __ InvokeFunction(function, expected, arguments_, | |
| 1076 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 1077 } | 1042 } |
| 1078 | 1043 |
| 1079 // Deferred code for fast API call case---clean preallocated space. | 1044 // Deferred code for fast API call case---clean preallocated space. |
| 1080 if (can_do_fast_api_call) { | 1045 if (can_do_fast_api_call) { |
| 1081 __ bind(&miss_cleanup); | 1046 __ bind(&miss_cleanup); |
| 1082 FreeSpaceForFastApiCall(masm); | 1047 FreeSpaceForFastApiCall(masm); |
| 1083 __ b(miss_label); | 1048 __ b(miss_label); |
| 1084 } | 1049 } |
| 1085 | 1050 |
| 1086 // Invoke a regular function. | 1051 // Invoke a regular function. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 IC::kLoadPropertyWithInterceptorOnly); | 1097 IC::kLoadPropertyWithInterceptorOnly); |
| 1133 __ pop(name_); // Restore the name. | 1098 __ pop(name_); // Restore the name. |
| 1134 __ pop(receiver); // Restore the holder. | 1099 __ pop(receiver); // Restore the holder. |
| 1135 } | 1100 } |
| 1136 // If interceptor returns no-result sentinel, call the constant function. | 1101 // If interceptor returns no-result sentinel, call the constant function. |
| 1137 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1102 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1138 __ cmp(r0, scratch); | 1103 __ cmp(r0, scratch); |
| 1139 __ b(ne, interceptor_succeeded); | 1104 __ b(ne, interceptor_succeeded); |
| 1140 } | 1105 } |
| 1141 | 1106 |
| 1142 StubCompiler* stub_compiler_; | 1107 CallStubCompiler* stub_compiler_; |
| 1143 const ParameterCount& arguments_; | 1108 const ParameterCount& arguments_; |
| 1144 Register name_; | 1109 Register name_; |
| 1145 ExtraICState extra_ic_state_; | 1110 ExtraICState extra_ic_state_; |
| 1146 }; | 1111 }; |
| 1147 | 1112 |
| 1148 | 1113 |
| 1149 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1114 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1150 __ Jump(code, RelocInfo::CODE_TARGET); | 1115 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1151 } | 1116 } |
| 1152 | 1117 |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 | 1499 |
| 1535 | 1500 |
| 1536 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1501 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1537 if (kind_ == Code::KEYED_CALL_IC) { | 1502 if (kind_ == Code::KEYED_CALL_IC) { |
| 1538 __ cmp(r2, Operand(name)); | 1503 __ cmp(r2, Operand(name)); |
| 1539 __ b(ne, miss); | 1504 __ b(ne, miss); |
| 1540 } | 1505 } |
| 1541 } | 1506 } |
| 1542 | 1507 |
| 1543 | 1508 |
| 1509 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1510 Register scratch, |
| 1511 Label* miss) { |
| 1512 __ JumpIfSmi(function, miss); |
| 1513 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE); |
| 1514 __ b(ne, miss); |
| 1515 } |
| 1516 |
| 1517 |
| 1544 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1518 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1545 Handle<Cell> cell, | 1519 Handle<Cell> cell, |
| 1546 Handle<JSFunction> function, | 1520 Handle<JSFunction> function, |
| 1547 Label* miss) { | 1521 Label* miss) { |
| 1548 // Get the value from the cell. | 1522 // Get the value from the cell. |
| 1549 __ mov(r3, Operand(cell)); | 1523 __ mov(r3, Operand(cell)); |
| 1550 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | 1524 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); |
| 1551 | 1525 |
| 1552 // Check that the cell contains the same function. | 1526 // Check that the cell contains the same function. |
| 1553 if (heap()->InNewSpace(*function)) { | 1527 if (heap()->InNewSpace(*function)) { |
| 1554 // We can't embed a pointer to a function in new space so we have | 1528 // We can't embed a pointer to a function in new space so we have |
| 1555 // to verify that the shared function info is unchanged. This has | 1529 // to verify that the shared function info is unchanged. This has |
| 1556 // the nice side effect that multiple closures based on the same | 1530 // the nice side effect that multiple closures based on the same |
| 1557 // function can all use this call IC. Before we load through the | 1531 // function can all use this call IC. Before we load through the |
| 1558 // function, we have to verify that it still is a function. | 1532 // function, we have to verify that it still is a function. |
| 1559 __ JumpIfSmi(r1, miss); | 1533 GenerateFunctionCheck(r1, r3, miss); |
| 1560 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | |
| 1561 __ b(ne, miss); | |
| 1562 | 1534 |
| 1563 // Check the shared function info. Make sure it hasn't changed. | 1535 // Check the shared function info. Make sure it hasn't changed. |
| 1564 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1536 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
| 1565 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1537 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1566 __ cmp(r4, r3); | 1538 __ cmp(r4, r3); |
| 1567 } else { | 1539 } else { |
| 1568 __ cmp(r1, Operand(function)); | 1540 __ cmp(r1, Operand(function)); |
| 1569 } | 1541 } |
| 1570 __ b(ne, miss); | 1542 __ b(ne, miss); |
| 1571 } | 1543 } |
| 1572 | 1544 |
| 1573 | 1545 |
| 1574 void CallStubCompiler::GenerateMissBranch() { | 1546 void CallStubCompiler::GenerateMissBranch() { |
| 1575 Handle<Code> code = | 1547 Handle<Code> code = |
| 1576 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1548 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1577 kind_, | 1549 kind_, |
| 1578 extra_state_); | 1550 extra_state()); |
| 1579 __ Jump(code, RelocInfo::CODE_TARGET); | 1551 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1580 } | 1552 } |
| 1581 | 1553 |
| 1582 | 1554 |
| 1583 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1555 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1584 Handle<JSObject> holder, | 1556 Handle<JSObject> holder, |
| 1585 PropertyIndex index, | 1557 PropertyIndex index, |
| 1586 Handle<Name> name) { | 1558 Handle<Name> name) { |
| 1587 Label miss; | 1559 Label miss; |
| 1588 | 1560 |
| 1589 Register reg = HandlerFrontendHeader( | 1561 Register reg = HandlerFrontendHeader( |
| 1590 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1562 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1591 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | 1563 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
| 1592 index.translate(holder), Representation::Tagged()); | 1564 index.translate(holder), Representation::Tagged()); |
| 1593 | 1565 GenerateJumpFunction(object, r1, &miss); |
| 1594 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | |
| 1595 | 1566 |
| 1596 HandlerFrontendFooter(&miss); | 1567 HandlerFrontendFooter(&miss); |
| 1597 | 1568 |
| 1598 // Return the generated code. | 1569 // Return the generated code. |
| 1599 return GetCode(Code::FAST, name); | 1570 return GetCode(Code::FAST, name); |
| 1600 } | 1571 } |
| 1601 | 1572 |
| 1602 | 1573 |
| 1603 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1574 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1604 Handle<Object> object, | 1575 Handle<Object> object, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1633 } | 1604 } |
| 1634 | 1605 |
| 1635 | 1606 |
| 1636 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1607 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1637 Handle<Object> object, | 1608 Handle<Object> object, |
| 1638 Handle<JSObject> holder, | 1609 Handle<JSObject> holder, |
| 1639 Handle<Cell> cell, | 1610 Handle<Cell> cell, |
| 1640 Handle<JSFunction> function, | 1611 Handle<JSFunction> function, |
| 1641 Handle<String> name, | 1612 Handle<String> name, |
| 1642 Code::StubType type) { | 1613 Code::StubType type) { |
| 1643 // If object is not an array or is observed, bail out to regular call. | 1614 // If object is not an array or is observed or sealed, bail out to regular |
| 1615 // call. |
| 1644 if (!object->IsJSArray() || | 1616 if (!object->IsJSArray() || |
| 1645 !cell.is_null() || | 1617 !cell.is_null() || |
| 1646 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1618 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1619 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1647 return Handle<Code>::null(); | 1620 return Handle<Code>::null(); |
| 1648 } | 1621 } |
| 1649 | 1622 |
| 1650 Label miss; | 1623 Label miss; |
| 1651 | 1624 |
| 1652 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1625 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1653 Register receiver = r0; | 1626 Register receiver = r0; |
| 1654 Register scratch = r1; | 1627 Register scratch = r1; |
| 1655 | 1628 |
| 1656 const int argc = arguments().immediate(); | 1629 const int argc = arguments().immediate(); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1876 } | 1849 } |
| 1877 | 1850 |
| 1878 | 1851 |
| 1879 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1852 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1880 Handle<Object> object, | 1853 Handle<Object> object, |
| 1881 Handle<JSObject> holder, | 1854 Handle<JSObject> holder, |
| 1882 Handle<Cell> cell, | 1855 Handle<Cell> cell, |
| 1883 Handle<JSFunction> function, | 1856 Handle<JSFunction> function, |
| 1884 Handle<String> name, | 1857 Handle<String> name, |
| 1885 Code::StubType type) { | 1858 Code::StubType type) { |
| 1886 // If object is not an array or is observed, bail out to regular call. | 1859 // If object is not an array or is observed or sealed, bail out to regular |
| 1860 // call. |
| 1887 if (!object->IsJSArray() || | 1861 if (!object->IsJSArray() || |
| 1888 !cell.is_null() || | 1862 !cell.is_null() || |
| 1889 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1863 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1864 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1890 return Handle<Code>::null(); | 1865 return Handle<Code>::null(); |
| 1891 } | 1866 } |
| 1892 | 1867 |
| 1893 Label miss, return_undefined, call_builtin; | 1868 Label miss, return_undefined, call_builtin; |
| 1894 Register receiver = r0; | 1869 Register receiver = r0; |
| 1895 Register scratch = r1; | 1870 Register scratch = r1; |
| 1896 Register elements = r3; | 1871 Register elements = r3; |
| 1897 | 1872 |
| 1898 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1873 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1899 | 1874 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 Code::StubType type) { | 1931 Code::StubType type) { |
| 1957 // If object is not a string, bail out to regular call. | 1932 // If object is not a string, bail out to regular call. |
| 1958 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1933 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 1959 | 1934 |
| 1960 Label miss; | 1935 Label miss; |
| 1961 Label name_miss; | 1936 Label name_miss; |
| 1962 Label index_out_of_range; | 1937 Label index_out_of_range; |
| 1963 Label* index_out_of_range_label = &index_out_of_range; | 1938 Label* index_out_of_range_label = &index_out_of_range; |
| 1964 | 1939 |
| 1965 if (kind_ == Code::CALL_IC && | 1940 if (kind_ == Code::CALL_IC && |
| 1966 (CallICBase::StringStubState::decode(extra_state_) == | 1941 (CallICBase::StringStubState::decode(extra_state()) == |
| 1967 DEFAULT_STRING_STUB)) { | 1942 DEFAULT_STRING_STUB)) { |
| 1968 index_out_of_range_label = &miss; | 1943 index_out_of_range_label = &miss; |
| 1969 } | 1944 } |
| 1970 | 1945 |
| 1971 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 1946 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 1972 | 1947 |
| 1973 Register receiver = r0; | 1948 Register receiver = r0; |
| 1974 Register index = r4; | 1949 Register index = r4; |
| 1975 Register result = r1; | 1950 Register result = r1; |
| 1976 const int argc = arguments().immediate(); | 1951 const int argc = arguments().immediate(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1999 if (index_out_of_range.is_linked()) { | 1974 if (index_out_of_range.is_linked()) { |
| 2000 __ bind(&index_out_of_range); | 1975 __ bind(&index_out_of_range); |
| 2001 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 1976 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
| 2002 __ Drop(argc + 1); | 1977 __ Drop(argc + 1); |
| 2003 __ Ret(); | 1978 __ Ret(); |
| 2004 } | 1979 } |
| 2005 | 1980 |
| 2006 __ bind(&miss); | 1981 __ bind(&miss); |
| 2007 // Restore function name in r2. | 1982 // Restore function name in r2. |
| 2008 __ Move(r2, name); | 1983 __ Move(r2, name); |
| 2009 __ bind(&name_miss); | 1984 HandlerFrontendFooter(&name_miss); |
| 2010 GenerateMissBranch(); | |
| 2011 | 1985 |
| 2012 // Return the generated code. | 1986 // Return the generated code. |
| 2013 return GetCode(type, name); | 1987 return GetCode(type, name); |
| 2014 } | 1988 } |
| 2015 | 1989 |
| 2016 | 1990 |
| 2017 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1991 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2018 Handle<Object> object, | 1992 Handle<Object> object, |
| 2019 Handle<JSObject> holder, | 1993 Handle<JSObject> holder, |
| 2020 Handle<Cell> cell, | 1994 Handle<Cell> cell, |
| 2021 Handle<JSFunction> function, | 1995 Handle<JSFunction> function, |
| 2022 Handle<String> name, | 1996 Handle<String> name, |
| 2023 Code::StubType type) { | 1997 Code::StubType type) { |
| 2024 // If object is not a string, bail out to regular call. | 1998 // If object is not a string, bail out to regular call. |
| 2025 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1999 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2026 | 2000 |
| 2027 const int argc = arguments().immediate(); | 2001 const int argc = arguments().immediate(); |
| 2028 Label miss; | 2002 Label miss; |
| 2029 Label name_miss; | 2003 Label name_miss; |
| 2030 Label index_out_of_range; | 2004 Label index_out_of_range; |
| 2031 Label* index_out_of_range_label = &index_out_of_range; | 2005 Label* index_out_of_range_label = &index_out_of_range; |
| 2032 if (kind_ == Code::CALL_IC && | 2006 if (kind_ == Code::CALL_IC && |
| 2033 (CallICBase::StringStubState::decode(extra_state_) == | 2007 (CallICBase::StringStubState::decode(extra_state()) == |
| 2034 DEFAULT_STRING_STUB)) { | 2008 DEFAULT_STRING_STUB)) { |
| 2035 index_out_of_range_label = &miss; | 2009 index_out_of_range_label = &miss; |
| 2036 } | 2010 } |
| 2037 | 2011 |
| 2038 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); | 2012 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2039 | 2013 |
| 2040 Register receiver = r0; | 2014 Register receiver = r0; |
| 2041 Register index = r4; | 2015 Register index = r4; |
| 2042 Register scratch = r3; | 2016 Register scratch = r3; |
| 2043 Register result = r1; | 2017 Register result = r1; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2066 if (index_out_of_range.is_linked()) { | 2040 if (index_out_of_range.is_linked()) { |
| 2067 __ bind(&index_out_of_range); | 2041 __ bind(&index_out_of_range); |
| 2068 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 2042 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
| 2069 __ Drop(argc + 1); | 2043 __ Drop(argc + 1); |
| 2070 __ Ret(); | 2044 __ Ret(); |
| 2071 } | 2045 } |
| 2072 | 2046 |
| 2073 __ bind(&miss); | 2047 __ bind(&miss); |
| 2074 // Restore function name in r2. | 2048 // Restore function name in r2. |
| 2075 __ Move(r2, name); | 2049 __ Move(r2, name); |
| 2076 __ bind(&name_miss); | 2050 HandlerFrontendFooter(&name_miss); |
| 2077 GenerateMissBranch(); | |
| 2078 | 2051 |
| 2079 // Return the generated code. | 2052 // Return the generated code. |
| 2080 return GetCode(type, name); | 2053 return GetCode(type, name); |
| 2081 } | 2054 } |
| 2082 | 2055 |
| 2083 | 2056 |
| 2084 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2057 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2085 Handle<Object> object, | 2058 Handle<Object> object, |
| 2086 Handle<JSObject> holder, | 2059 Handle<JSObject> holder, |
| 2087 Handle<Cell> cell, | 2060 Handle<Cell> cell, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2114 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 2087 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
| 2115 | 2088 |
| 2116 StringCharFromCodeGenerator generator(code, r0); | 2089 StringCharFromCodeGenerator generator(code, r0); |
| 2117 generator.GenerateFast(masm()); | 2090 generator.GenerateFast(masm()); |
| 2118 __ Drop(argc + 1); | 2091 __ Drop(argc + 1); |
| 2119 __ Ret(); | 2092 __ Ret(); |
| 2120 | 2093 |
| 2121 StubRuntimeCallHelper call_helper; | 2094 StubRuntimeCallHelper call_helper; |
| 2122 generator.GenerateSlow(masm(), call_helper); | 2095 generator.GenerateSlow(masm(), call_helper); |
| 2123 | 2096 |
| 2124 // Tail call the full function. We do not have to patch the receiver | |
| 2125 // because the function makes no use of it. | |
| 2126 __ bind(&slow); | 2097 __ bind(&slow); |
| 2127 ParameterCount expected(function); | 2098 // We do not have to patch the receiver because the function makes no use of |
| 2128 __ InvokeFunction(function, expected, arguments(), | 2099 // it. |
| 2129 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2100 GenerateJumpFunctionIgnoreReceiver(function); |
| 2130 | 2101 |
| 2131 HandlerFrontendFooter(&miss); | 2102 HandlerFrontendFooter(&miss); |
| 2132 | 2103 |
| 2133 // Return the generated code. | 2104 // Return the generated code. |
| 2134 return GetCode(type, name); | 2105 return GetCode(type, name); |
| 2135 } | 2106 } |
| 2136 | 2107 |
| 2137 | 2108 |
| 2138 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2109 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2139 Handle<Object> object, | 2110 Handle<Object> object, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2207 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. | 2178 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. |
| 2208 // If result doesn't fit into an smi, branch to slow. | 2179 // If result doesn't fit into an smi, branch to slow. |
| 2209 __ SmiTag(r0, SetCC); | 2180 __ SmiTag(r0, SetCC); |
| 2210 __ b(vs, &slow); | 2181 __ b(vs, &slow); |
| 2211 | 2182 |
| 2212 __ bind(&just_return); | 2183 __ bind(&just_return); |
| 2213 __ Drop(argc + 1); | 2184 __ Drop(argc + 1); |
| 2214 __ Ret(); | 2185 __ Ret(); |
| 2215 | 2186 |
| 2216 __ bind(&slow); | 2187 __ bind(&slow); |
| 2217 // Tail call the full function. We do not have to patch the receiver | 2188 // We do not have to patch the receiver because the function makes no use of |
| 2218 // because the function makes no use of it. | 2189 // it. |
| 2219 ParameterCount expected(function); | 2190 GenerateJumpFunctionIgnoreReceiver(function); |
| 2220 __ InvokeFunction(function, expected, arguments(), | |
| 2221 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
| 2222 | 2191 |
| 2223 HandlerFrontendFooter(&miss); | 2192 HandlerFrontendFooter(&miss); |
| 2224 | 2193 |
| 2225 // Return the generated code. | 2194 // Return the generated code. |
| 2226 return GetCode(type, name); | 2195 return GetCode(type, name); |
| 2227 } | 2196 } |
| 2228 | 2197 |
| 2229 | 2198 |
| 2230 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2199 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2231 Handle<Object> object, | 2200 Handle<Object> object, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2289 __ bind(&negative_sign); | 2258 __ bind(&negative_sign); |
| 2290 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); | 2259 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); |
| 2291 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2260 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 2292 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 2261 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 2293 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); | 2262 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); |
| 2294 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 2263 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 2295 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2264 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 2296 __ Drop(argc + 1); | 2265 __ Drop(argc + 1); |
| 2297 __ Ret(); | 2266 __ Ret(); |
| 2298 | 2267 |
| 2299 // Tail call the full function. We do not have to patch the receiver | |
| 2300 // because the function makes no use of it. | |
| 2301 __ bind(&slow); | 2268 __ bind(&slow); |
| 2302 ParameterCount expected(function); | 2269 // We do not have to patch the receiver because the function makes no use of |
| 2303 __ InvokeFunction(function, expected, arguments(), | 2270 // it. |
| 2304 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2271 GenerateJumpFunctionIgnoreReceiver(function); |
| 2305 | 2272 |
| 2306 HandlerFrontendFooter(&miss); | 2273 HandlerFrontendFooter(&miss); |
| 2307 | 2274 |
| 2308 // Return the generated code. | 2275 // Return the generated code. |
| 2309 return GetCode(type, name); | 2276 return GetCode(type, name); |
| 2310 } | 2277 } |
| 2311 | 2278 |
| 2312 | 2279 |
| 2313 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2280 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2314 const CallOptimization& optimization, | 2281 const CallOptimization& optimization, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2347 // Check that the maps haven't changed and find a Holder as a side effect. | 2314 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2348 CheckPrototypes( | 2315 CheckPrototypes( |
| 2349 IC::CurrentTypeOf(object, isolate()), | 2316 IC::CurrentTypeOf(object, isolate()), |
| 2350 r1, holder, r0, r3, r4, name, depth, &miss); | 2317 r1, holder, r0, r3, r4, name, depth, &miss); |
| 2351 | 2318 |
| 2352 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2319 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
| 2353 | 2320 |
| 2354 __ bind(&miss); | 2321 __ bind(&miss); |
| 2355 FreeSpaceForFastApiCall(masm()); | 2322 FreeSpaceForFastApiCall(masm()); |
| 2356 | 2323 |
| 2357 __ bind(&miss_before_stack_reserved); | 2324 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2358 GenerateMissBranch(); | |
| 2359 | 2325 |
| 2360 // Return the generated code. | 2326 // Return the generated code. |
| 2361 return GetCode(function); | 2327 return GetCode(function); |
| 2362 } | 2328 } |
| 2363 | 2329 |
| 2364 | 2330 |
| 2365 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2331 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2366 Label success; | 2332 Label success; |
| 2367 // Check that the object is a boolean. | 2333 // Check that the object is a boolean. |
| 2368 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2334 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2465 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2431 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2466 reg = CheckPrototypes( | 2432 reg = CheckPrototypes( |
| 2467 IC::CurrentTypeOf(prototype, isolate()), | 2433 IC::CurrentTypeOf(prototype, isolate()), |
| 2468 r1, holder, r1, r3, r4, name, miss); | 2434 r1, holder, r1, r3, r4, name, miss); |
| 2469 } | 2435 } |
| 2470 | 2436 |
| 2471 return reg; | 2437 return reg; |
| 2472 } | 2438 } |
| 2473 | 2439 |
| 2474 | 2440 |
| 2475 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2441 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2476 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2442 Register function, |
| 2477 ? CALL_AS_FUNCTION | 2443 Label* miss) { |
| 2478 : CALL_AS_METHOD; | 2444 ASSERT(function.is(r1)); |
| 2479 ParameterCount expected(function); | 2445 // Check that the function really is a function. |
| 2480 __ InvokeFunction(function, expected, arguments(), | 2446 GenerateFunctionCheck(function, r3, miss); |
| 2481 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2447 PatchGlobalProxy(object); |
| 2448 |
| 2449 // Invoke the function. |
| 2450 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, |
| 2451 NullCallWrapper(), call_kind()); |
| 2482 } | 2452 } |
| 2483 | 2453 |
| 2484 | 2454 |
| 2485 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2486 Handle<Object> object, | |
| 2487 Handle<JSObject> holder, | |
| 2488 Handle<Name> name, | |
| 2489 CheckType check, | |
| 2490 Handle<JSFunction> function) { | |
| 2491 if (HasCustomCallGenerator(function)) { | |
| 2492 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2493 Handle<Cell>::null(), | |
| 2494 function, Handle<String>::cast(name), | |
| 2495 Code::FAST); | |
| 2496 // A null handle means bail out to the regular compiler code below. | |
| 2497 if (!code.is_null()) return code; | |
| 2498 } | |
| 2499 | |
| 2500 Label miss; | |
| 2501 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2502 PatchGlobalProxy(object); | |
| 2503 CompileHandlerBackend(function); | |
| 2504 HandlerFrontendFooter(&miss); | |
| 2505 | |
| 2506 // Return the generated code. | |
| 2507 return GetCode(function); | |
| 2508 } | |
| 2509 | |
| 2510 | |
| 2511 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2455 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2512 Handle<JSObject> holder, | 2456 Handle<JSObject> holder, |
| 2513 Handle<Name> name) { | 2457 Handle<Name> name) { |
| 2514 Label miss; | 2458 Label miss; |
| 2515 GenerateNameCheck(name, &miss); | 2459 GenerateNameCheck(name, &miss); |
| 2516 | 2460 |
| 2517 // Get the number of arguments. | 2461 // Get the number of arguments. |
| 2518 const int argc = arguments().immediate(); | 2462 const int argc = arguments().immediate(); |
| 2519 LookupResult lookup(isolate()); | 2463 LookupResult lookup(isolate()); |
| 2520 LookupPostInterceptor(holder, name, &lookup); | 2464 LookupPostInterceptor(holder, name, &lookup); |
| 2521 | 2465 |
| 2522 // Get the receiver from the stack. | 2466 // Get the receiver from the stack. |
| 2523 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2467 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2524 | 2468 |
| 2525 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); | 2469 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state()); |
| 2526 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, | 2470 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, |
| 2527 &miss); | 2471 &miss); |
| 2528 | 2472 |
| 2529 // Move returned value, the function to call, to r1. | 2473 // Move returned value, the function to call, to r1. |
| 2530 __ mov(r1, r0); | 2474 __ mov(r1, r0); |
| 2531 // Restore receiver. | 2475 // Restore receiver. |
| 2532 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2476 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 2533 | 2477 |
| 2534 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 2478 GenerateJumpFunction(object, r1, &miss); |
| 2535 | 2479 |
| 2536 // Handle call cache miss. | 2480 HandlerFrontendFooter(&miss); |
| 2537 __ bind(&miss); | |
| 2538 GenerateMissBranch(); | |
| 2539 | 2481 |
| 2540 // Return the generated code. | 2482 // Return the generated code. |
| 2541 return GetCode(Code::FAST, name); | 2483 return GetCode(Code::FAST, name); |
| 2542 } | 2484 } |
| 2543 | 2485 |
| 2544 | 2486 |
| 2545 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2487 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2546 Handle<JSObject> object, | 2488 Handle<JSObject> object, |
| 2547 Handle<GlobalObject> holder, | 2489 Handle<GlobalObject> holder, |
| 2548 Handle<PropertyCell> cell, | 2490 Handle<PropertyCell> cell, |
| 2549 Handle<JSFunction> function, | 2491 Handle<JSFunction> function, |
| 2550 Handle<Name> name) { | 2492 Handle<Name> name) { |
| 2551 if (HasCustomCallGenerator(function)) { | 2493 if (HasCustomCallGenerator(function)) { |
| 2552 Handle<Code> code = CompileCustomCall( | 2494 Handle<Code> code = CompileCustomCall( |
| 2553 object, holder, cell, function, Handle<String>::cast(name), | 2495 object, holder, cell, function, Handle<String>::cast(name), |
| 2554 Code::NORMAL); | 2496 Code::NORMAL); |
| 2555 // A null handle means bail out to the regular compiler code below. | 2497 // A null handle means bail out to the regular compiler code below. |
| 2556 if (!code.is_null()) return code; | 2498 if (!code.is_null()) return code; |
| 2557 } | 2499 } |
| 2558 | 2500 |
| 2559 Label miss; | 2501 Label miss; |
| 2560 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2502 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2503 // Potentially loads a closure that matches the shared function info of the |
| 2504 // function, rather than function. |
| 2561 GenerateLoadFunctionFromCell(cell, function, &miss); | 2505 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2562 PatchGlobalProxy(object); | |
| 2563 | 2506 |
| 2564 // Set up the context (function already in r1). | |
| 2565 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
| 2566 | |
| 2567 // Jump to the cached code (tail call). | |
| 2568 Counters* counters = isolate()->counters(); | 2507 Counters* counters = isolate()->counters(); |
| 2569 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2508 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
| 2570 ParameterCount expected(function->shared()->formal_parameter_count()); | 2509 GenerateJumpFunction(object, r1, function); |
| 2571 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2572 ? CALL_AS_FUNCTION | |
| 2573 : CALL_AS_METHOD; | |
| 2574 // We call indirectly through the code field in the function to | |
| 2575 // allow recompilation to take effect without changing any of the | |
| 2576 // call sites. | |
| 2577 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | |
| 2578 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | |
| 2579 NullCallWrapper(), call_kind); | |
| 2580 | |
| 2581 HandlerFrontendFooter(&miss); | 2510 HandlerFrontendFooter(&miss); |
| 2582 | 2511 |
| 2583 // Return the generated code. | 2512 // Return the generated code. |
| 2584 return GetCode(Code::NORMAL, name); | 2513 return GetCode(Code::NORMAL, name); |
| 2585 } | 2514 } |
| 2586 | 2515 |
| 2587 | 2516 |
| 2588 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2517 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2589 Handle<JSObject> object, | 2518 Handle<JSObject> object, |
| 2590 Handle<JSObject> holder, | 2519 Handle<JSObject> holder, |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2962 // ----------------------------------- | 2891 // ----------------------------------- |
| 2963 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2892 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2964 } | 2893 } |
| 2965 | 2894 |
| 2966 | 2895 |
| 2967 #undef __ | 2896 #undef __ |
| 2968 | 2897 |
| 2969 } } // namespace v8::internal | 2898 } } // namespace v8::internal |
| 2970 | 2899 |
| 2971 #endif // V8_TARGET_ARCH_ARM | 2900 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |