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 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
726 Label* label, | 726 Label* label, |
727 Handle<Name> name) { | 727 Handle<Name> name) { |
728 if (!label->is_unused()) { | 728 if (!label->is_unused()) { |
729 __ bind(label); | 729 __ bind(label); |
730 __ li(this->name(), Operand(name)); | 730 __ li(this->name(), Operand(name)); |
731 } | 731 } |
732 } | 732 } |
733 | 733 |
734 | 734 |
| 735 static void GenerateCallFunction(MacroAssembler* masm, |
| 736 Handle<Object> object, |
| 737 const ParameterCount& arguments, |
| 738 Label* miss, |
| 739 ExtraICState extra_ic_state) { |
| 740 // ----------- S t a t e ------------- |
| 741 // -- a0: receiver |
| 742 // -- a1: function to call |
| 743 // ----------------------------------- |
| 744 // Check that the function really is a function. |
| 745 __ JumpIfSmi(a1, miss); |
| 746 __ GetObjectType(a1, a3, a3); |
| 747 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 748 |
| 749 if (object->IsGlobalObject()) { |
| 750 const int argc = arguments.immediate(); |
| 751 const int receiver_offset = argc * kPointerSize; |
| 752 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 753 __ sw(a3, MemOperand(sp, receiver_offset)); |
| 754 } |
| 755 |
| 756 // Invoke the function. |
| 757 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
| 758 ? CALL_AS_FUNCTION |
| 759 : CALL_AS_METHOD; |
| 760 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 761 } |
| 762 |
| 763 |
735 static void PushInterceptorArguments(MacroAssembler* masm, | 764 static void PushInterceptorArguments(MacroAssembler* masm, |
736 Register receiver, | 765 Register receiver, |
737 Register holder, | 766 Register holder, |
738 Register name, | 767 Register name, |
739 Handle<JSObject> holder_obj) { | 768 Handle<JSObject> holder_obj) { |
740 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 769 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
741 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 770 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
742 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 771 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
743 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 772 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
744 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 773 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 ASSERT(!scratch.is(values[i])); | 935 ASSERT(!scratch.is(values[i])); |
907 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); | 936 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); |
908 } | 937 } |
909 | 938 |
910 GenerateFastApiDirectCall(masm, optimization, argc, true); | 939 GenerateFastApiDirectCall(masm, optimization, argc, true); |
911 } | 940 } |
912 | 941 |
913 | 942 |
914 class CallInterceptorCompiler BASE_EMBEDDED { | 943 class CallInterceptorCompiler BASE_EMBEDDED { |
915 public: | 944 public: |
916 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 945 CallInterceptorCompiler(StubCompiler* stub_compiler, |
917 const ParameterCount& arguments, | 946 const ParameterCount& arguments, |
918 Register name, | 947 Register name, |
919 ExtraICState extra_ic_state) | 948 ExtraICState extra_ic_state) |
920 : stub_compiler_(stub_compiler), | 949 : stub_compiler_(stub_compiler), |
921 arguments_(arguments), | 950 arguments_(arguments), |
922 name_(name), | 951 name_(name), |
923 extra_ic_state_(extra_ic_state) {} | 952 extra_ic_state_(extra_ic_state) {} |
924 | 953 |
925 void Compile(MacroAssembler* masm, | 954 void Compile(MacroAssembler* masm, |
926 Handle<JSObject> object, | 955 Handle<JSObject> object, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 // safe to omit it here, as if present, it should be fetched | 1047 // safe to omit it here, as if present, it should be fetched |
1019 // by the previous CheckPrototypes. | 1048 // by the previous CheckPrototypes. |
1020 ASSERT(depth2 == kInvalidProtoDepth); | 1049 ASSERT(depth2 == kInvalidProtoDepth); |
1021 } | 1050 } |
1022 | 1051 |
1023 // Invoke function. | 1052 // Invoke function. |
1024 if (can_do_fast_api_call) { | 1053 if (can_do_fast_api_call) { |
1025 GenerateFastApiDirectCall( | 1054 GenerateFastApiDirectCall( |
1026 masm, optimization, arguments_.immediate(), false); | 1055 masm, optimization, arguments_.immediate(), false); |
1027 } else { | 1056 } else { |
| 1057 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 1058 ? CALL_AS_FUNCTION |
| 1059 : CALL_AS_METHOD; |
1028 Handle<JSFunction> function = optimization.constant_function(); | 1060 Handle<JSFunction> function = optimization.constant_function(); |
1029 stub_compiler_->GenerateJumpFunction(object, function); | 1061 ParameterCount expected(function); |
| 1062 __ InvokeFunction(function, expected, arguments_, |
| 1063 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
1030 } | 1064 } |
1031 | 1065 |
1032 // Deferred code for fast API call case---clean preallocated space. | 1066 // Deferred code for fast API call case---clean preallocated space. |
1033 if (can_do_fast_api_call) { | 1067 if (can_do_fast_api_call) { |
1034 __ bind(&miss_cleanup); | 1068 __ bind(&miss_cleanup); |
1035 FreeSpaceForFastApiCall(masm); | 1069 FreeSpaceForFastApiCall(masm); |
1036 __ Branch(miss_label); | 1070 __ Branch(miss_label); |
1037 } | 1071 } |
1038 | 1072 |
1039 // Invoke a regular function. | 1073 // Invoke a regular function. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 masm, receiver, holder, name_, holder_obj, | 1119 masm, receiver, holder, name_, holder_obj, |
1086 IC::kLoadPropertyWithInterceptorOnly); | 1120 IC::kLoadPropertyWithInterceptorOnly); |
1087 __ pop(name_); // Restore the name. | 1121 __ pop(name_); // Restore the name. |
1088 __ pop(receiver); // Restore the holder. | 1122 __ pop(receiver); // Restore the holder. |
1089 } | 1123 } |
1090 // If interceptor returns no-result sentinel, call the constant function. | 1124 // If interceptor returns no-result sentinel, call the constant function. |
1091 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1125 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
1092 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); | 1126 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); |
1093 } | 1127 } |
1094 | 1128 |
1095 CallStubCompiler* stub_compiler_; | 1129 StubCompiler* stub_compiler_; |
1096 const ParameterCount& arguments_; | 1130 const ParameterCount& arguments_; |
1097 Register name_; | 1131 Register name_; |
1098 ExtraICState extra_ic_state_; | 1132 ExtraICState extra_ic_state_; |
1099 }; | 1133 }; |
1100 | 1134 |
1101 | 1135 |
1102 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1136 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
1103 __ Jump(code, RelocInfo::CODE_TARGET); | 1137 __ Jump(code, RelocInfo::CODE_TARGET); |
1104 } | 1138 } |
1105 | 1139 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 } | 1520 } |
1487 | 1521 |
1488 | 1522 |
1489 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1523 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1490 if (kind_ == Code::KEYED_CALL_IC) { | 1524 if (kind_ == Code::KEYED_CALL_IC) { |
1491 __ Branch(miss, ne, a2, Operand(name)); | 1525 __ Branch(miss, ne, a2, Operand(name)); |
1492 } | 1526 } |
1493 } | 1527 } |
1494 | 1528 |
1495 | 1529 |
1496 void CallStubCompiler::GenerateFunctionCheck(Register function, | |
1497 Register scratch, | |
1498 Label* miss) { | |
1499 __ JumpIfSmi(function, miss); | |
1500 __ GetObjectType(function, scratch, scratch); | |
1501 __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); | |
1502 } | |
1503 | |
1504 | |
1505 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1530 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1506 Handle<Cell> cell, | 1531 Handle<Cell> cell, |
1507 Handle<JSFunction> function, | 1532 Handle<JSFunction> function, |
1508 Label* miss) { | 1533 Label* miss) { |
1509 // Get the value from the cell. | 1534 // Get the value from the cell. |
1510 __ li(a3, Operand(cell)); | 1535 __ li(a3, Operand(cell)); |
1511 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); | 1536 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); |
1512 | 1537 |
1513 // Check that the cell contains the same function. | 1538 // Check that the cell contains the same function. |
1514 if (heap()->InNewSpace(*function)) { | 1539 if (heap()->InNewSpace(*function)) { |
1515 // We can't embed a pointer to a function in new space so we have | 1540 // We can't embed a pointer to a function in new space so we have |
1516 // to verify that the shared function info is unchanged. This has | 1541 // to verify that the shared function info is unchanged. This has |
1517 // the nice side effect that multiple closures based on the same | 1542 // the nice side effect that multiple closures based on the same |
1518 // function can all use this call IC. Before we load through the | 1543 // function can all use this call IC. Before we load through the |
1519 // function, we have to verify that it still is a function. | 1544 // function, we have to verify that it still is a function. |
1520 GenerateFunctionCheck(a1, a3, miss); | 1545 __ JumpIfSmi(a1, miss); |
| 1546 __ GetObjectType(a1, a3, a3); |
| 1547 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); |
1521 | 1548 |
1522 // Check the shared function info. Make sure it hasn't changed. | 1549 // Check the shared function info. Make sure it hasn't changed. |
1523 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); | 1550 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); |
1524 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1551 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
1525 __ Branch(miss, ne, t0, Operand(a3)); | 1552 __ Branch(miss, ne, t0, Operand(a3)); |
1526 } else { | 1553 } else { |
1527 __ Branch(miss, ne, a1, Operand(function)); | 1554 __ Branch(miss, ne, a1, Operand(function)); |
1528 } | 1555 } |
1529 } | 1556 } |
1530 | 1557 |
(...skipping 10 matching lines...) Expand all Loading... |
1541 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1568 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1542 Handle<JSObject> holder, | 1569 Handle<JSObject> holder, |
1543 PropertyIndex index, | 1570 PropertyIndex index, |
1544 Handle<Name> name) { | 1571 Handle<Name> name) { |
1545 Label miss; | 1572 Label miss; |
1546 | 1573 |
1547 Register reg = HandlerFrontendHeader( | 1574 Register reg = HandlerFrontendHeader( |
1548 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1575 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1549 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), | 1576 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), |
1550 index.translate(holder), Representation::Tagged()); | 1577 index.translate(holder), Representation::Tagged()); |
1551 GenerateJumpFunction(object, a1, &miss); | 1578 |
| 1579 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
1552 | 1580 |
1553 HandlerFrontendFooter(&miss); | 1581 HandlerFrontendFooter(&miss); |
1554 | 1582 |
1555 // Return the generated code. | 1583 // Return the generated code. |
1556 return GetCode(Code::FAST, name); | 1584 return GetCode(Code::FAST, name); |
1557 } | 1585 } |
1558 | 1586 |
1559 | 1587 |
1560 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1588 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1561 Handle<Object> object, | 1589 Handle<Object> object, |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1953 | 1981 |
1954 if (index_out_of_range.is_linked()) { | 1982 if (index_out_of_range.is_linked()) { |
1955 __ bind(&index_out_of_range); | 1983 __ bind(&index_out_of_range); |
1956 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 1984 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
1957 __ DropAndRet(argc + 1); | 1985 __ DropAndRet(argc + 1); |
1958 } | 1986 } |
1959 | 1987 |
1960 __ bind(&miss); | 1988 __ bind(&miss); |
1961 // Restore function name in a2. | 1989 // Restore function name in a2. |
1962 __ li(a2, name); | 1990 __ li(a2, name); |
1963 HandlerFrontendFooter(&name_miss); | 1991 __ bind(&name_miss); |
| 1992 GenerateMissBranch(); |
1964 | 1993 |
1965 // Return the generated code. | 1994 // Return the generated code. |
1966 return GetCode(type, name); | 1995 return GetCode(type, name); |
1967 } | 1996 } |
1968 | 1997 |
1969 | 1998 |
1970 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1999 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
1971 Handle<Object> object, | 2000 Handle<Object> object, |
1972 Handle<JSObject> holder, | 2001 Handle<JSObject> holder, |
1973 Handle<Cell> cell, | 2002 Handle<Cell> cell, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2017 | 2046 |
2018 if (index_out_of_range.is_linked()) { | 2047 if (index_out_of_range.is_linked()) { |
2019 __ bind(&index_out_of_range); | 2048 __ bind(&index_out_of_range); |
2020 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 2049 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
2021 __ DropAndRet(argc + 1); | 2050 __ DropAndRet(argc + 1); |
2022 } | 2051 } |
2023 | 2052 |
2024 __ bind(&miss); | 2053 __ bind(&miss); |
2025 // Restore function name in a2. | 2054 // Restore function name in a2. |
2026 __ li(a2, name); | 2055 __ li(a2, name); |
2027 HandlerFrontendFooter(&name_miss); | 2056 __ bind(&name_miss); |
| 2057 GenerateMissBranch(); |
2028 | 2058 |
2029 // Return the generated code. | 2059 // Return the generated code. |
2030 return GetCode(type, name); | 2060 return GetCode(type, name); |
2031 } | 2061 } |
2032 | 2062 |
2033 | 2063 |
2034 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2064 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2035 Handle<Object> object, | 2065 Handle<Object> object, |
2036 Handle<JSObject> holder, | 2066 Handle<JSObject> holder, |
2037 Handle<Cell> cell, | 2067 Handle<Cell> cell, |
(...skipping 25 matching lines...) Expand all Loading... |
2063 // Convert the smi code to uint16. | 2093 // Convert the smi code to uint16. |
2064 __ And(code, code, Operand(Smi::FromInt(0xffff))); | 2094 __ And(code, code, Operand(Smi::FromInt(0xffff))); |
2065 | 2095 |
2066 StringCharFromCodeGenerator generator(code, v0); | 2096 StringCharFromCodeGenerator generator(code, v0); |
2067 generator.GenerateFast(masm()); | 2097 generator.GenerateFast(masm()); |
2068 __ DropAndRet(argc + 1); | 2098 __ DropAndRet(argc + 1); |
2069 | 2099 |
2070 StubRuntimeCallHelper call_helper; | 2100 StubRuntimeCallHelper call_helper; |
2071 generator.GenerateSlow(masm(), call_helper); | 2101 generator.GenerateSlow(masm(), call_helper); |
2072 | 2102 |
| 2103 // Tail call the full function. We do not have to patch the receiver |
| 2104 // because the function makes no use of it. |
2073 __ bind(&slow); | 2105 __ bind(&slow); |
2074 // We do not have to patch the receiver because the function makes no use of | 2106 ParameterCount expected(function); |
2075 // it. | 2107 __ InvokeFunction(function, expected, arguments(), |
2076 GenerateJumpFunctionIgnoreReceiver(function); | 2108 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2077 | 2109 |
2078 HandlerFrontendFooter(&miss); | 2110 HandlerFrontendFooter(&miss); |
2079 | 2111 |
2080 // Return the generated code. | 2112 // Return the generated code. |
2081 return GetCode(type, name); | 2113 return GetCode(type, name); |
2082 } | 2114 } |
2083 | 2115 |
2084 | 2116 |
2085 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2117 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2086 Handle<Object> object, | 2118 Handle<Object> object, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2172 // Restore FCSR and return. | 2204 // Restore FCSR and return. |
2173 __ ctc1(a3, FCSR); | 2205 __ ctc1(a3, FCSR); |
2174 | 2206 |
2175 __ DropAndRet(argc + 1); | 2207 __ DropAndRet(argc + 1); |
2176 | 2208 |
2177 __ bind(&wont_fit_smi); | 2209 __ bind(&wont_fit_smi); |
2178 // Restore FCSR and fall to slow case. | 2210 // Restore FCSR and fall to slow case. |
2179 __ ctc1(a3, FCSR); | 2211 __ ctc1(a3, FCSR); |
2180 | 2212 |
2181 __ bind(&slow); | 2213 __ bind(&slow); |
2182 // We do not have to patch the receiver because the function makes no use of | 2214 // Tail call the full function. We do not have to patch the receiver |
2183 // it. | 2215 // because the function makes no use of it. |
2184 GenerateJumpFunctionIgnoreReceiver(function); | 2216 ParameterCount expected(function); |
| 2217 __ InvokeFunction(function, expected, arguments(), |
| 2218 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2185 | 2219 |
2186 HandlerFrontendFooter(&miss); | 2220 HandlerFrontendFooter(&miss); |
2187 | 2221 |
2188 // Return the generated code. | 2222 // Return the generated code. |
2189 return GetCode(type, name); | 2223 return GetCode(type, name); |
2190 } | 2224 } |
2191 | 2225 |
2192 | 2226 |
2193 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2227 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2194 Handle<Object> object, | 2228 Handle<Object> object, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 // number. | 2285 // number. |
2252 __ bind(&negative_sign); | 2286 __ bind(&negative_sign); |
2253 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); | 2287 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); |
2254 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2288 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
2255 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); | 2289 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); |
2256 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); | 2290 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); |
2257 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 2291 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
2258 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2292 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
2259 __ DropAndRet(argc + 1); | 2293 __ DropAndRet(argc + 1); |
2260 | 2294 |
| 2295 // Tail call the full function. We do not have to patch the receiver |
| 2296 // because the function makes no use of it. |
2261 __ bind(&slow); | 2297 __ bind(&slow); |
2262 // We do not have to patch the receiver because the function makes no use of | 2298 ParameterCount expected(function); |
2263 // it. | 2299 __ InvokeFunction(function, expected, arguments(), |
2264 GenerateJumpFunctionIgnoreReceiver(function); | 2300 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2265 | 2301 |
2266 HandlerFrontendFooter(&miss); | 2302 HandlerFrontendFooter(&miss); |
2267 | 2303 |
2268 // Return the generated code. | 2304 // Return the generated code. |
2269 return GetCode(type, name); | 2305 return GetCode(type, name); |
2270 } | 2306 } |
2271 | 2307 |
2272 | 2308 |
2273 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2309 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2274 const CallOptimization& optimization, | 2310 const CallOptimization& optimization, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2309 // Check that the maps haven't changed and find a Holder as a side effect. | 2345 // Check that the maps haven't changed and find a Holder as a side effect. |
2310 CheckPrototypes( | 2346 CheckPrototypes( |
2311 IC::CurrentTypeOf(object, isolate()), | 2347 IC::CurrentTypeOf(object, isolate()), |
2312 a1, holder, a0, a3, t0, name, depth, &miss); | 2348 a1, holder, a0, a3, t0, name, depth, &miss); |
2313 | 2349 |
2314 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2350 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
2315 | 2351 |
2316 __ bind(&miss); | 2352 __ bind(&miss); |
2317 FreeSpaceForFastApiCall(masm()); | 2353 FreeSpaceForFastApiCall(masm()); |
2318 | 2354 |
2319 HandlerFrontendFooter(&miss_before_stack_reserved); | 2355 __ bind(&miss_before_stack_reserved); |
| 2356 GenerateMissBranch(); |
2320 | 2357 |
2321 // Return the generated code. | 2358 // Return the generated code. |
2322 return GetCode(function); | 2359 return GetCode(function); |
2323 } | 2360 } |
2324 | 2361 |
2325 | 2362 |
2326 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2363 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2327 Label success; | 2364 Label success; |
2328 // Check that the object is a boolean. | 2365 // Check that the object is a boolean. |
2329 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2366 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
2330 __ Branch(&success, eq, object, Operand(at)); | 2367 __ Branch(&success, eq, object, Operand(at)); |
2331 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 2368 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
2332 __ Branch(miss, ne, object, Operand(at)); | 2369 __ Branch(miss, ne, object, Operand(at)); |
2333 __ bind(&success); | 2370 __ bind(&success); |
2334 } | 2371 } |
2335 | 2372 |
2336 | 2373 |
2337 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2374 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2338 if (!object.is_null() && object->IsGlobalObject()) { | 2375 if (object->IsGlobalObject()) { |
2339 const int argc = arguments().immediate(); | 2376 const int argc = arguments().immediate(); |
2340 const int receiver_offset = argc * kPointerSize; | 2377 const int receiver_offset = argc * kPointerSize; |
2341 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | 2378 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
2342 __ sw(a3, MemOperand(sp, receiver_offset)); | 2379 __ sw(a3, MemOperand(sp, receiver_offset)); |
2343 } | 2380 } |
2344 } | 2381 } |
2345 | 2382 |
2346 | 2383 |
2347 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2384 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2348 Handle<JSObject> holder, | 2385 Handle<JSObject> holder, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2424 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2461 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2425 reg = CheckPrototypes( | 2462 reg = CheckPrototypes( |
2426 IC::CurrentTypeOf(prototype, isolate()), | 2463 IC::CurrentTypeOf(prototype, isolate()), |
2427 a1, holder, a1, a3, t0, name, miss); | 2464 a1, holder, a1, a3, t0, name, miss); |
2428 } | 2465 } |
2429 | 2466 |
2430 return reg; | 2467 return reg; |
2431 } | 2468 } |
2432 | 2469 |
2433 | 2470 |
2434 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | 2471 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2435 Register function, | 2472 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2436 Label* miss) { | 2473 ? CALL_AS_FUNCTION |
2437 ASSERT(function.is(a1)); | 2474 : CALL_AS_METHOD; |
2438 // Check that the function really is a function. | 2475 ParameterCount expected(function); |
2439 GenerateFunctionCheck(function, a3, miss); | 2476 __ InvokeFunction(function, expected, arguments(), |
2440 if (!function.is(a1)) __ mov(a1, function); | 2477 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2441 PatchGlobalProxy(object); | |
2442 // Invoke the function. | |
2443 __ InvokeFunction(a1, arguments(), JUMP_FUNCTION, | |
2444 NullCallWrapper(), call_kind()); | |
2445 } | 2478 } |
2446 | 2479 |
2447 | 2480 |
| 2481 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2482 Handle<Object> object, |
| 2483 Handle<JSObject> holder, |
| 2484 Handle<Name> name, |
| 2485 CheckType check, |
| 2486 Handle<JSFunction> function) { |
| 2487 if (HasCustomCallGenerator(function)) { |
| 2488 Handle<Code> code = CompileCustomCall(object, holder, |
| 2489 Handle<Cell>::null(), |
| 2490 function, Handle<String>::cast(name), |
| 2491 Code::FAST); |
| 2492 // A null handle means bail out to the regular compiler code below. |
| 2493 if (!code.is_null()) return code; |
| 2494 } |
| 2495 |
| 2496 Label miss; |
| 2497 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 2498 PatchGlobalProxy(object); |
| 2499 CompileHandlerBackend(function); |
| 2500 HandlerFrontendFooter(&miss); |
| 2501 |
| 2502 // Return the generated code. |
| 2503 return GetCode(function); |
| 2504 } |
| 2505 |
| 2506 |
2448 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2507 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2449 Handle<JSObject> holder, | 2508 Handle<JSObject> holder, |
2450 Handle<Name> name) { | 2509 Handle<Name> name) { |
2451 Label miss; | 2510 Label miss; |
2452 | 2511 |
2453 GenerateNameCheck(name, &miss); | 2512 GenerateNameCheck(name, &miss); |
2454 | 2513 |
2455 // Get the number of arguments. | 2514 // Get the number of arguments. |
2456 const int argc = arguments().immediate(); | 2515 const int argc = arguments().immediate(); |
2457 LookupResult lookup(isolate()); | 2516 LookupResult lookup(isolate()); |
2458 LookupPostInterceptor(holder, name, &lookup); | 2517 LookupPostInterceptor(holder, name, &lookup); |
2459 | 2518 |
2460 // Get the receiver from the stack. | 2519 // Get the receiver from the stack. |
2461 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2520 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
2462 | 2521 |
2463 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); | 2522 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); |
2464 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, | 2523 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, |
2465 &miss); | 2524 &miss); |
2466 | 2525 |
2467 // Move returned value, the function to call, to a1. | 2526 // Move returned value, the function to call, to a1. |
2468 __ mov(a1, v0); | 2527 __ mov(a1, v0); |
2469 // Restore receiver. | 2528 // Restore receiver. |
2470 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2529 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
2471 | 2530 |
2472 GenerateJumpFunction(object, a1, &miss); | 2531 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
2473 | 2532 |
2474 HandlerFrontendFooter(&miss); | 2533 // Handle call cache miss. |
| 2534 __ bind(&miss); |
| 2535 GenerateMissBranch(); |
2475 | 2536 |
2476 // Return the generated code. | 2537 // Return the generated code. |
2477 return GetCode(Code::FAST, name); | 2538 return GetCode(Code::FAST, name); |
2478 } | 2539 } |
2479 | 2540 |
2480 | 2541 |
2481 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2542 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2482 Handle<JSObject> object, | 2543 Handle<JSObject> object, |
2483 Handle<GlobalObject> holder, | 2544 Handle<GlobalObject> holder, |
2484 Handle<PropertyCell> cell, | 2545 Handle<PropertyCell> cell, |
2485 Handle<JSFunction> function, | 2546 Handle<JSFunction> function, |
2486 Handle<Name> name) { | 2547 Handle<Name> name) { |
2487 if (HasCustomCallGenerator(function)) { | 2548 if (HasCustomCallGenerator(function)) { |
2488 Handle<Code> code = CompileCustomCall( | 2549 Handle<Code> code = CompileCustomCall( |
2489 object, holder, cell, function, Handle<String>::cast(name), | 2550 object, holder, cell, function, Handle<String>::cast(name), |
2490 Code::NORMAL); | 2551 Code::NORMAL); |
2491 // A null handle means bail out to the regular compiler code below. | 2552 // A null handle means bail out to the regular compiler code below. |
2492 if (!code.is_null()) return code; | 2553 if (!code.is_null()) return code; |
2493 } | 2554 } |
2494 | 2555 |
2495 Label miss; | 2556 Label miss; |
2496 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2557 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2497 // Potentially loads a closure that matches the shared function info of the | |
2498 // function, rather than function. | |
2499 GenerateLoadFunctionFromCell(cell, function, &miss); | 2558 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2559 PatchGlobalProxy(object); |
| 2560 |
| 2561 // Set up the context (function already in r1). |
| 2562 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2563 |
| 2564 // Jump to the cached code (tail call). |
2500 Counters* counters = isolate()->counters(); | 2565 Counters* counters = isolate()->counters(); |
2501 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2566 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
2502 GenerateJumpFunction(object, a1, function); | 2567 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2568 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2569 ? CALL_AS_FUNCTION |
| 2570 : CALL_AS_METHOD; |
| 2571 // We call indirectly through the code field in the function to |
| 2572 // allow recompilation to take effect without changing any of the |
| 2573 // call sites. |
| 2574 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 2575 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, |
| 2576 NullCallWrapper(), call_kind); |
| 2577 |
2503 HandlerFrontendFooter(&miss); | 2578 HandlerFrontendFooter(&miss); |
2504 | 2579 |
2505 // Return the generated code. | 2580 // Return the generated code. |
2506 return GetCode(Code::NORMAL, name); | 2581 return GetCode(Code::NORMAL, name); |
2507 } | 2582 } |
2508 | 2583 |
2509 | 2584 |
2510 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2585 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2511 Handle<JSObject> object, | 2586 Handle<JSObject> object, |
2512 Handle<JSObject> holder, | 2587 Handle<JSObject> holder, |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2882 // ----------------------------------- | 2957 // ----------------------------------- |
2883 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2958 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2884 } | 2959 } |
2885 | 2960 |
2886 | 2961 |
2887 #undef __ | 2962 #undef __ |
2888 | 2963 |
2889 } } // namespace v8::internal | 2964 } } // namespace v8::internal |
2890 | 2965 |
2891 #endif // V8_TARGET_ARCH_MIPS | 2966 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |