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 Code::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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
953 ASSERT(!scratch.is(values[i])); | 923 ASSERT(!scratch.is(values[i])); |
954 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); | 924 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); |
955 } | 925 } |
956 | 926 |
957 GenerateFastApiDirectCall(masm, optimization, argc, true); | 927 GenerateFastApiDirectCall(masm, optimization, argc, true); |
958 } | 928 } |
959 | 929 |
960 | 930 |
961 class CallInterceptorCompiler BASE_EMBEDDED { | 931 class CallInterceptorCompiler BASE_EMBEDDED { |
962 public: | 932 public: |
963 CallInterceptorCompiler(StubCompiler* stub_compiler, | 933 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
964 const ParameterCount& arguments, | 934 const ParameterCount& arguments, |
965 Register name, | 935 Register name, |
966 Code::ExtraICState extra_ic_state) | 936 Code::ExtraICState extra_ic_state) |
967 : stub_compiler_(stub_compiler), | 937 : stub_compiler_(stub_compiler), |
968 arguments_(arguments), | 938 arguments_(arguments), |
969 name_(name), | 939 name_(name), |
970 extra_ic_state_(extra_ic_state) {} | 940 extra_ic_state_(extra_ic_state) {} |
971 | 941 |
972 void Compile(MacroAssembler* masm, | 942 void Compile(MacroAssembler* masm, |
973 Handle<JSObject> object, | 943 Handle<JSObject> object, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1065 // safe to omit it here, as if present, it should be fetched | 1035 // safe to omit it here, as if present, it should be fetched |
1066 // by the previous CheckPrototypes. | 1036 // by the previous CheckPrototypes. |
1067 ASSERT(depth2 == kInvalidProtoDepth); | 1037 ASSERT(depth2 == kInvalidProtoDepth); |
1068 } | 1038 } |
1069 | 1039 |
1070 // Invoke function. | 1040 // Invoke function. |
1071 if (can_do_fast_api_call) { | 1041 if (can_do_fast_api_call) { |
1072 GenerateFastApiDirectCall( | 1042 GenerateFastApiDirectCall( |
1073 masm, optimization, arguments_.immediate(), false); | 1043 masm, optimization, arguments_.immediate(), false); |
1074 } else { | 1044 } else { |
1075 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
1076 ? CALL_AS_FUNCTION | |
1077 : CALL_AS_METHOD; | |
1078 Handle<JSFunction> function = optimization.constant_function(); | 1045 Handle<JSFunction> function = optimization.constant_function(); |
1079 ParameterCount expected(function); | 1046 stub_compiler_->GenerateCallFunction(object, function); |
1080 __ InvokeFunction(function, expected, arguments_, | |
1081 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
1082 } | 1047 } |
1083 | 1048 |
1084 // Deferred code for fast API call case---clean preallocated space. | 1049 // Deferred code for fast API call case---clean preallocated space. |
1085 if (can_do_fast_api_call) { | 1050 if (can_do_fast_api_call) { |
1086 __ bind(&miss_cleanup); | 1051 __ bind(&miss_cleanup); |
1087 FreeSpaceForFastApiCall(masm); | 1052 FreeSpaceForFastApiCall(masm); |
1088 __ b(miss_label); | 1053 __ b(miss_label); |
1089 } | 1054 } |
1090 | 1055 |
1091 // Invoke a regular function. | 1056 // Invoke a regular function. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 holder_obj); | 1104 holder_obj); |
1140 __ pop(name_); // Restore the name. | 1105 __ pop(name_); // Restore the name. |
1141 __ pop(receiver); // Restore the holder. | 1106 __ pop(receiver); // Restore the holder. |
1142 } | 1107 } |
1143 // If interceptor returns no-result sentinel, call the constant function. | 1108 // If interceptor returns no-result sentinel, call the constant function. |
1144 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1109 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
1145 __ cmp(r0, scratch); | 1110 __ cmp(r0, scratch); |
1146 __ b(ne, interceptor_succeeded); | 1111 __ b(ne, interceptor_succeeded); |
1147 } | 1112 } |
1148 | 1113 |
1149 StubCompiler* stub_compiler_; | 1114 CallStubCompiler* stub_compiler_; |
1150 const ParameterCount& arguments_; | 1115 const ParameterCount& arguments_; |
1151 Register name_; | 1116 Register name_; |
1152 Code::ExtraICState extra_ic_state_; | 1117 Code::ExtraICState extra_ic_state_; |
1153 }; | 1118 }; |
1154 | 1119 |
1155 | 1120 |
1156 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1121 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
1157 __ Jump(code, RelocInfo::CODE_TARGET); | 1122 __ Jump(code, RelocInfo::CODE_TARGET); |
1158 } | 1123 } |
1159 | 1124 |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1542 | 1507 |
1543 | 1508 |
1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1509 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1545 if (kind_ == Code::KEYED_CALL_IC) { | 1510 if (kind_ == Code::KEYED_CALL_IC) { |
1546 __ cmp(r2, Operand(name)); | 1511 __ cmp(r2, Operand(name)); |
1547 __ b(ne, miss); | 1512 __ b(ne, miss); |
1548 } | 1513 } |
1549 } | 1514 } |
1550 | 1515 |
1551 | 1516 |
1517 void CallStubCompiler::GenerateFunctionCheck(Register function, | |
1518 Register scratch, | |
1519 Label* miss) { | |
1520 __ JumpIfSmi(function, miss); | |
1521 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE); | |
1522 __ b(ne, miss); | |
1523 } | |
1524 | |
1525 | |
1552 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1526 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1553 Handle<Cell> cell, | 1527 Handle<Cell> cell, |
1554 Handle<JSFunction> function, | 1528 Handle<JSFunction> function, |
1555 Label* miss) { | 1529 Label* miss) { |
1556 // Get the value from the cell. | 1530 // Get the value from the cell. |
1557 __ mov(r3, Operand(cell)); | 1531 __ mov(r3, Operand(cell)); |
1558 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | 1532 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); |
1559 | 1533 |
1560 // Check that the cell contains the same function. | 1534 // Check that the cell contains the same function. |
1561 if (heap()->InNewSpace(*function)) { | 1535 if (heap()->InNewSpace(*function)) { |
1562 // We can't embed a pointer to a function in new space so we have | 1536 // We can't embed a pointer to a function in new space so we have |
1563 // to verify that the shared function info is unchanged. This has | 1537 // to verify that the shared function info is unchanged. This has |
1564 // the nice side effect that multiple closures based on the same | 1538 // the nice side effect that multiple closures based on the same |
1565 // function can all use this call IC. Before we load through the | 1539 // function can all use this call IC. Before we load through the |
1566 // function, we have to verify that it still is a function. | 1540 // function, we have to verify that it still is a function. |
1567 __ JumpIfSmi(r1, miss); | 1541 GenerateFunctionCheck(r1, r3, miss); |
1568 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | |
1569 __ b(ne, miss); | |
1570 | 1542 |
1571 // Check the shared function info. Make sure it hasn't changed. | 1543 // Check the shared function info. Make sure it hasn't changed. |
1572 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1544 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
1573 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1545 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1574 __ cmp(r4, r3); | 1546 __ cmp(r4, r3); |
1575 } else { | 1547 } else { |
1576 __ cmp(r1, Operand(function)); | 1548 __ cmp(r1, Operand(function)); |
1577 } | 1549 } |
1578 __ b(ne, miss); | 1550 __ b(ne, miss); |
1579 } | 1551 } |
(...skipping 11 matching lines...) Expand all Loading... | |
1591 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1563 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1592 Handle<JSObject> holder, | 1564 Handle<JSObject> holder, |
1593 PropertyIndex index, | 1565 PropertyIndex index, |
1594 Handle<Name> name) { | 1566 Handle<Name> name) { |
1595 Label miss; | 1567 Label miss; |
1596 | 1568 |
1597 Register reg = HandlerFrontendHeader( | 1569 Register reg = HandlerFrontendHeader( |
1598 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1570 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1599 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | 1571 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
1600 index.translate(holder), Representation::Tagged()); | 1572 index.translate(holder), Representation::Tagged()); |
1601 | 1573 GenerateCallFunction(object, r1, &miss); |
1602 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | |
1603 | 1574 |
1604 HandlerFrontendFooter(&miss); | 1575 HandlerFrontendFooter(&miss); |
1605 | 1576 |
1606 // Return the generated code. | 1577 // Return the generated code. |
1607 return GetCode(Code::FAST, name); | 1578 return GetCode(Code::FAST, name); |
1608 } | 1579 } |
1609 | 1580 |
1610 | 1581 |
1611 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1582 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1612 Handle<Object> object, | 1583 Handle<Object> object, |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2007 if (index_out_of_range.is_linked()) { | 1978 if (index_out_of_range.is_linked()) { |
2008 __ bind(&index_out_of_range); | 1979 __ bind(&index_out_of_range); |
2009 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 1980 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
2010 __ Drop(argc + 1); | 1981 __ Drop(argc + 1); |
2011 __ Ret(); | 1982 __ Ret(); |
2012 } | 1983 } |
2013 | 1984 |
2014 __ bind(&miss); | 1985 __ bind(&miss); |
2015 // Restore function name in r2. | 1986 // Restore function name in r2. |
2016 __ Move(r2, name); | 1987 __ Move(r2, name); |
2017 __ bind(&name_miss); | 1988 HandlerFrontendFooter(&name_miss); |
2018 GenerateMissBranch(); | |
2019 | 1989 |
2020 // Return the generated code. | 1990 // Return the generated code. |
2021 return GetCode(type, name); | 1991 return GetCode(type, name); |
2022 } | 1992 } |
2023 | 1993 |
2024 | 1994 |
2025 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1995 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2026 Handle<Object> object, | 1996 Handle<Object> object, |
2027 Handle<JSObject> holder, | 1997 Handle<JSObject> holder, |
2028 Handle<Cell> cell, | 1998 Handle<Cell> cell, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2074 if (index_out_of_range.is_linked()) { | 2044 if (index_out_of_range.is_linked()) { |
2075 __ bind(&index_out_of_range); | 2045 __ bind(&index_out_of_range); |
2076 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 2046 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
2077 __ Drop(argc + 1); | 2047 __ Drop(argc + 1); |
2078 __ Ret(); | 2048 __ Ret(); |
2079 } | 2049 } |
2080 | 2050 |
2081 __ bind(&miss); | 2051 __ bind(&miss); |
2082 // Restore function name in r2. | 2052 // Restore function name in r2. |
2083 __ Move(r2, name); | 2053 __ Move(r2, name); |
2084 __ bind(&name_miss); | 2054 HandlerFrontendFooter(&name_miss); |
2085 GenerateMissBranch(); | |
2086 | 2055 |
2087 // Return the generated code. | 2056 // Return the generated code. |
2088 return GetCode(type, name); | 2057 return GetCode(type, name); |
2089 } | 2058 } |
2090 | 2059 |
2091 | 2060 |
2092 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2061 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2093 Handle<Object> object, | 2062 Handle<Object> object, |
2094 Handle<JSObject> holder, | 2063 Handle<JSObject> holder, |
2095 Handle<Cell> cell, | 2064 Handle<Cell> cell, |
(...skipping 26 matching lines...) Expand all Loading... | |
2122 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 2091 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
2123 | 2092 |
2124 StringCharFromCodeGenerator generator(code, r0); | 2093 StringCharFromCodeGenerator generator(code, r0); |
2125 generator.GenerateFast(masm()); | 2094 generator.GenerateFast(masm()); |
2126 __ Drop(argc + 1); | 2095 __ Drop(argc + 1); |
2127 __ Ret(); | 2096 __ Ret(); |
2128 | 2097 |
2129 StubRuntimeCallHelper call_helper; | 2098 StubRuntimeCallHelper call_helper; |
2130 generator.GenerateSlow(masm(), call_helper); | 2099 generator.GenerateSlow(masm(), call_helper); |
2131 | 2100 |
2132 // Tail call the full function. We do not have to patch the receiver | |
2133 // because the function makes no use of it. | |
2134 __ bind(&slow); | 2101 __ bind(&slow); |
2135 ParameterCount expected(function); | 2102 // We do not have to patch the receiver because the function makes no use of |
2136 __ InvokeFunction(function, expected, arguments(), | 2103 // it. |
2137 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2104 GenerateCallFunction(Handle<Object>::null(), function); |
Igor Sheludko
2013/11/28 13:06:08
Consider introducing different function for such a
Toon Verwaest
2013/11/28 15:24:09
Done.
| |
2138 | 2105 |
2139 HandlerFrontendFooter(&miss); | 2106 HandlerFrontendFooter(&miss); |
2140 | 2107 |
2141 // Return the generated code. | 2108 // Return the generated code. |
2142 return GetCode(type, name); | 2109 return GetCode(type, name); |
2143 } | 2110 } |
2144 | 2111 |
2145 | 2112 |
2146 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2113 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2147 Handle<Object> object, | 2114 Handle<Object> object, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2215 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. | 2182 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. |
2216 // If result doesn't fit into an smi, branch to slow. | 2183 // If result doesn't fit into an smi, branch to slow. |
2217 __ SmiTag(r0, SetCC); | 2184 __ SmiTag(r0, SetCC); |
2218 __ b(vs, &slow); | 2185 __ b(vs, &slow); |
2219 | 2186 |
2220 __ bind(&just_return); | 2187 __ bind(&just_return); |
2221 __ Drop(argc + 1); | 2188 __ Drop(argc + 1); |
2222 __ Ret(); | 2189 __ Ret(); |
2223 | 2190 |
2224 __ bind(&slow); | 2191 __ bind(&slow); |
2225 // Tail call the full function. We do not have to patch the receiver | 2192 // We do not have to patch the receiver because the function makes no use of |
2226 // because the function makes no use of it. | 2193 // it. |
2227 ParameterCount expected(function); | 2194 GenerateCallFunction(Handle<Object>::null(), function); |
2228 __ InvokeFunction(function, expected, arguments(), | |
2229 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
2230 | 2195 |
2231 HandlerFrontendFooter(&miss); | 2196 HandlerFrontendFooter(&miss); |
2232 | 2197 |
2233 // Return the generated code. | 2198 // Return the generated code. |
2234 return GetCode(type, name); | 2199 return GetCode(type, name); |
2235 } | 2200 } |
2236 | 2201 |
2237 | 2202 |
2238 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2203 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2239 Handle<Object> object, | 2204 Handle<Object> object, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2297 __ bind(&negative_sign); | 2262 __ bind(&negative_sign); |
2298 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); | 2263 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); |
2299 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2264 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
2300 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 2265 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
2301 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); | 2266 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); |
2302 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 2267 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
2303 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2268 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
2304 __ Drop(argc + 1); | 2269 __ Drop(argc + 1); |
2305 __ Ret(); | 2270 __ Ret(); |
2306 | 2271 |
2307 // Tail call the full function. We do not have to patch the receiver | |
2308 // because the function makes no use of it. | |
2309 __ bind(&slow); | 2272 __ bind(&slow); |
2310 ParameterCount expected(function); | 2273 // We do not have to patch the receiver because the function makes no use of |
2311 __ InvokeFunction(function, expected, arguments(), | 2274 // it. |
2312 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2275 GenerateCallFunction(Handle<Object>::null(), function); |
2313 | 2276 |
2314 HandlerFrontendFooter(&miss); | 2277 HandlerFrontendFooter(&miss); |
2315 | 2278 |
2316 // Return the generated code. | 2279 // Return the generated code. |
2317 return GetCode(type, name); | 2280 return GetCode(type, name); |
2318 } | 2281 } |
2319 | 2282 |
2320 | 2283 |
2321 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2284 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2322 const CallOptimization& optimization, | 2285 const CallOptimization& optimization, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2355 // Check that the maps haven't changed and find a Holder as a side effect. | 2318 // Check that the maps haven't changed and find a Holder as a side effect. |
2356 CheckPrototypes( | 2319 CheckPrototypes( |
2357 IC::CurrentTypeOf(object, isolate()), | 2320 IC::CurrentTypeOf(object, isolate()), |
2358 r1, holder, r0, r3, r4, name, depth, &miss); | 2321 r1, holder, r0, r3, r4, name, depth, &miss); |
2359 | 2322 |
2360 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2323 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
2361 | 2324 |
2362 __ bind(&miss); | 2325 __ bind(&miss); |
2363 FreeSpaceForFastApiCall(masm()); | 2326 FreeSpaceForFastApiCall(masm()); |
2364 | 2327 |
2365 __ bind(&miss_before_stack_reserved); | 2328 HandlerFrontendFooter(&miss_before_stack_reserved); |
2366 GenerateMissBranch(); | |
2367 | 2329 |
2368 // Return the generated code. | 2330 // Return the generated code. |
2369 return GetCode(function); | 2331 return GetCode(function); |
2370 } | 2332 } |
2371 | 2333 |
2372 | 2334 |
2373 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2335 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2374 Label success; | 2336 Label success; |
2375 // Check that the object is a boolean. | 2337 // Check that the object is a boolean. |
2376 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2338 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
2377 __ cmp(object, ip); | 2339 __ cmp(object, ip); |
2378 __ b(eq, &success); | 2340 __ b(eq, &success); |
2379 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2341 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
2380 __ cmp(object, ip); | 2342 __ cmp(object, ip); |
2381 __ b(ne, miss); | 2343 __ b(ne, miss); |
2382 __ bind(&success); | 2344 __ bind(&success); |
2383 } | 2345 } |
2384 | 2346 |
2385 | 2347 |
2386 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2348 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2387 if (object->IsGlobalObject()) { | 2349 if (!object.is_null() && object->IsGlobalObject()) { |
2388 const int argc = arguments().immediate(); | 2350 const int argc = arguments().immediate(); |
2389 const int receiver_offset = argc * kPointerSize; | 2351 const int receiver_offset = argc * kPointerSize; |
2390 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 2352 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
2391 __ str(r3, MemOperand(sp, receiver_offset)); | 2353 __ str(r3, MemOperand(sp, receiver_offset)); |
2392 } | 2354 } |
2393 } | 2355 } |
2394 | 2356 |
2395 | 2357 |
2396 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2358 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2397 Handle<JSObject> holder, | 2359 Handle<JSObject> holder, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2473 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2435 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2474 reg = CheckPrototypes( | 2436 reg = CheckPrototypes( |
2475 IC::CurrentTypeOf(prototype, isolate()), | 2437 IC::CurrentTypeOf(prototype, isolate()), |
2476 r1, holder, r1, r3, r4, name, miss); | 2438 r1, holder, r1, r3, r4, name, miss); |
2477 } | 2439 } |
2478 | 2440 |
2479 return reg; | 2441 return reg; |
2480 } | 2442 } |
2481 | 2443 |
2482 | 2444 |
2483 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2445 void CallStubCompiler::GenerateCallFunction(Handle<Object> object, |
2484 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2446 Register function, |
2485 ? CALL_AS_FUNCTION | 2447 Label* miss) { |
2486 : CALL_AS_METHOD; | 2448 ASSERT(function.is(r1)); |
2487 ParameterCount expected(function); | 2449 // Check that the function really is a function. |
2488 __ InvokeFunction(function, expected, arguments(), | 2450 GenerateFunctionCheck(function, r3, miss); |
2489 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2451 if (!function.is(r1)) __ mov(r1, function); |
2452 PatchGlobalProxy(object); | |
2453 | |
2454 // Invoke the function. | |
2455 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, | |
2456 NullCallWrapper(), call_kind()); | |
2490 } | 2457 } |
2491 | 2458 |
2492 | 2459 |
2493 Handle<Code> CallStubCompiler::CompileCallConstant( | |
2494 Handle<Object> object, | |
2495 Handle<JSObject> holder, | |
2496 Handle<Name> name, | |
2497 CheckType check, | |
2498 Handle<JSFunction> function) { | |
2499 if (HasCustomCallGenerator(function)) { | |
2500 Handle<Code> code = CompileCustomCall(object, holder, | |
2501 Handle<Cell>::null(), | |
2502 function, Handle<String>::cast(name), | |
2503 Code::FAST); | |
2504 // A null handle means bail out to the regular compiler code below. | |
2505 if (!code.is_null()) return code; | |
2506 } | |
2507 | |
2508 Label miss; | |
2509 HandlerFrontendHeader(object, holder, name, check, &miss); | |
2510 PatchGlobalProxy(object); | |
2511 CompileHandlerBackend(function); | |
2512 HandlerFrontendFooter(&miss); | |
2513 | |
2514 // Return the generated code. | |
2515 return GetCode(function); | |
2516 } | |
2517 | |
2518 | |
2519 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2460 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2520 Handle<JSObject> holder, | 2461 Handle<JSObject> holder, |
2521 Handle<Name> name) { | 2462 Handle<Name> name) { |
2522 Label miss; | 2463 Label miss; |
2523 GenerateNameCheck(name, &miss); | 2464 GenerateNameCheck(name, &miss); |
2524 | 2465 |
2525 // Get the number of arguments. | 2466 // Get the number of arguments. |
2526 const int argc = arguments().immediate(); | 2467 const int argc = arguments().immediate(); |
2527 LookupResult lookup(isolate()); | 2468 LookupResult lookup(isolate()); |
2528 LookupPostInterceptor(holder, name, &lookup); | 2469 LookupPostInterceptor(holder, name, &lookup); |
2529 | 2470 |
2530 // Get the receiver from the stack. | 2471 // Get the receiver from the stack. |
2531 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2472 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2532 | 2473 |
2533 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); | 2474 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); |
2534 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, | 2475 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, |
2535 &miss); | 2476 &miss); |
2536 | 2477 |
2537 // Move returned value, the function to call, to r1. | 2478 // Move returned value, the function to call, to r1. |
2538 __ mov(r1, r0); | 2479 __ mov(r1, r0); |
2539 // Restore receiver. | 2480 // Restore receiver. |
2540 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2481 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
2541 | 2482 |
2542 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 2483 GenerateCallFunction(object, r0, &miss); |
2543 | 2484 |
2544 // Handle call cache miss. | 2485 HandlerFrontendFooter(&miss); |
2545 __ bind(&miss); | |
2546 GenerateMissBranch(); | |
2547 | 2486 |
2548 // Return the generated code. | 2487 // Return the generated code. |
2549 return GetCode(Code::FAST, name); | 2488 return GetCode(Code::FAST, name); |
2550 } | 2489 } |
2551 | 2490 |
2552 | 2491 |
2553 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2492 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2554 Handle<JSObject> object, | 2493 Handle<JSObject> object, |
2555 Handle<GlobalObject> holder, | 2494 Handle<GlobalObject> holder, |
2556 Handle<PropertyCell> cell, | 2495 Handle<PropertyCell> cell, |
2557 Handle<JSFunction> function, | 2496 Handle<JSFunction> function, |
2558 Handle<Name> name) { | 2497 Handle<Name> name) { |
2559 if (HasCustomCallGenerator(function)) { | 2498 if (HasCustomCallGenerator(function)) { |
2560 Handle<Code> code = CompileCustomCall( | 2499 Handle<Code> code = CompileCustomCall( |
2561 object, holder, cell, function, Handle<String>::cast(name), | 2500 object, holder, cell, function, Handle<String>::cast(name), |
2562 Code::NORMAL); | 2501 Code::NORMAL); |
2563 // A null handle means bail out to the regular compiler code below. | 2502 // A null handle means bail out to the regular compiler code below. |
2564 if (!code.is_null()) return code; | 2503 if (!code.is_null()) return code; |
2565 } | 2504 } |
2566 | 2505 |
2567 Label miss; | 2506 Label miss; |
2568 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2507 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2508 // Potentially loads a closure that matches the shared function info of the | |
2509 // function, rather than function. | |
2569 GenerateLoadFunctionFromCell(cell, function, &miss); | 2510 GenerateLoadFunctionFromCell(cell, function, &miss); |
2570 PatchGlobalProxy(object); | |
2571 | 2511 |
2572 // Set up the context (function already in r1). | |
2573 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
2574 | |
2575 // Jump to the cached code (tail call). | |
2576 Counters* counters = isolate()->counters(); | 2512 Counters* counters = isolate()->counters(); |
2577 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2513 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
2578 ParameterCount expected(function->shared()->formal_parameter_count()); | 2514 GenerateCallFunction(object, r1, function); |
2579 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
2580 ? CALL_AS_FUNCTION | |
2581 : CALL_AS_METHOD; | |
2582 // We call indirectly through the code field in the function to | |
2583 // allow recompilation to take effect without changing any of the | |
2584 // call sites. | |
2585 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | |
2586 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | |
2587 NullCallWrapper(), call_kind); | |
2588 | |
2589 HandlerFrontendFooter(&miss); | 2515 HandlerFrontendFooter(&miss); |
2590 | 2516 |
2591 // Return the generated code. | 2517 // Return the generated code. |
2592 return GetCode(Code::NORMAL, name); | 2518 return GetCode(Code::NORMAL, name); |
2593 } | 2519 } |
2594 | 2520 |
2595 | 2521 |
2596 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2522 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2597 Handle<JSObject> object, | 2523 Handle<JSObject> object, |
2598 Handle<JSObject> holder, | 2524 Handle<JSObject> holder, |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2973 // ----------------------------------- | 2899 // ----------------------------------- |
2974 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2900 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2975 } | 2901 } |
2976 | 2902 |
2977 | 2903 |
2978 #undef __ | 2904 #undef __ |
2979 | 2905 |
2980 } } // namespace v8::internal | 2906 } } // namespace v8::internal |
2981 | 2907 |
2982 #endif // V8_TARGET_ARCH_ARM | 2908 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |