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 |
745 static void PushInterceptorArguments(MacroAssembler* masm, | 775 static void PushInterceptorArguments(MacroAssembler* masm, |
746 Register receiver, | 776 Register receiver, |
747 Register holder, | 777 Register holder, |
748 Register name, | 778 Register name, |
749 Handle<JSObject> holder_obj) { | 779 Handle<JSObject> holder_obj) { |
750 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 780 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
751 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 781 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
752 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 782 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
753 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 783 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
754 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 784 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 ASSERT(!scratch.is(values[i])); | 948 ASSERT(!scratch.is(values[i])); |
919 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); | 949 __ str(receiver, MemOperand(sp, index-- * kPointerSize)); |
920 } | 950 } |
921 | 951 |
922 GenerateFastApiDirectCall(masm, optimization, argc, true); | 952 GenerateFastApiDirectCall(masm, optimization, argc, true); |
923 } | 953 } |
924 | 954 |
925 | 955 |
926 class CallInterceptorCompiler BASE_EMBEDDED { | 956 class CallInterceptorCompiler BASE_EMBEDDED { |
927 public: | 957 public: |
928 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 958 CallInterceptorCompiler(StubCompiler* stub_compiler, |
929 const ParameterCount& arguments, | 959 const ParameterCount& arguments, |
930 Register name, | 960 Register name, |
931 ExtraICState extra_ic_state) | 961 ExtraICState extra_ic_state) |
932 : stub_compiler_(stub_compiler), | 962 : stub_compiler_(stub_compiler), |
933 arguments_(arguments), | 963 arguments_(arguments), |
934 name_(name), | 964 name_(name), |
935 extra_ic_state_(extra_ic_state) {} | 965 extra_ic_state_(extra_ic_state) {} |
936 | 966 |
937 void Compile(MacroAssembler* masm, | 967 void Compile(MacroAssembler* masm, |
938 Handle<JSObject> object, | 968 Handle<JSObject> object, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 // safe to omit it here, as if present, it should be fetched | 1060 // safe to omit it here, as if present, it should be fetched |
1031 // by the previous CheckPrototypes. | 1061 // by the previous CheckPrototypes. |
1032 ASSERT(depth2 == kInvalidProtoDepth); | 1062 ASSERT(depth2 == kInvalidProtoDepth); |
1033 } | 1063 } |
1034 | 1064 |
1035 // Invoke function. | 1065 // Invoke function. |
1036 if (can_do_fast_api_call) { | 1066 if (can_do_fast_api_call) { |
1037 GenerateFastApiDirectCall( | 1067 GenerateFastApiDirectCall( |
1038 masm, optimization, arguments_.immediate(), false); | 1068 masm, optimization, arguments_.immediate(), false); |
1039 } else { | 1069 } else { |
| 1070 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 1071 ? CALL_AS_FUNCTION |
| 1072 : CALL_AS_METHOD; |
1040 Handle<JSFunction> function = optimization.constant_function(); | 1073 Handle<JSFunction> function = optimization.constant_function(); |
1041 stub_compiler_->GenerateJumpFunction(object, function); | 1074 ParameterCount expected(function); |
| 1075 __ InvokeFunction(function, expected, arguments_, |
| 1076 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
1042 } | 1077 } |
1043 | 1078 |
1044 // Deferred code for fast API call case---clean preallocated space. | 1079 // Deferred code for fast API call case---clean preallocated space. |
1045 if (can_do_fast_api_call) { | 1080 if (can_do_fast_api_call) { |
1046 __ bind(&miss_cleanup); | 1081 __ bind(&miss_cleanup); |
1047 FreeSpaceForFastApiCall(masm); | 1082 FreeSpaceForFastApiCall(masm); |
1048 __ b(miss_label); | 1083 __ b(miss_label); |
1049 } | 1084 } |
1050 | 1085 |
1051 // Invoke a regular function. | 1086 // Invoke a regular function. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 IC::kLoadPropertyWithInterceptorOnly); | 1132 IC::kLoadPropertyWithInterceptorOnly); |
1098 __ pop(name_); // Restore the name. | 1133 __ pop(name_); // Restore the name. |
1099 __ pop(receiver); // Restore the holder. | 1134 __ pop(receiver); // Restore the holder. |
1100 } | 1135 } |
1101 // If interceptor returns no-result sentinel, call the constant function. | 1136 // If interceptor returns no-result sentinel, call the constant function. |
1102 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1137 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
1103 __ cmp(r0, scratch); | 1138 __ cmp(r0, scratch); |
1104 __ b(ne, interceptor_succeeded); | 1139 __ b(ne, interceptor_succeeded); |
1105 } | 1140 } |
1106 | 1141 |
1107 CallStubCompiler* stub_compiler_; | 1142 StubCompiler* stub_compiler_; |
1108 const ParameterCount& arguments_; | 1143 const ParameterCount& arguments_; |
1109 Register name_; | 1144 Register name_; |
1110 ExtraICState extra_ic_state_; | 1145 ExtraICState extra_ic_state_; |
1111 }; | 1146 }; |
1112 | 1147 |
1113 | 1148 |
1114 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1149 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
1115 __ Jump(code, RelocInfo::CODE_TARGET); | 1150 __ Jump(code, RelocInfo::CODE_TARGET); |
1116 } | 1151 } |
1117 | 1152 |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 | 1534 |
1500 | 1535 |
1501 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1536 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1502 if (kind_ == Code::KEYED_CALL_IC) { | 1537 if (kind_ == Code::KEYED_CALL_IC) { |
1503 __ cmp(r2, Operand(name)); | 1538 __ cmp(r2, Operand(name)); |
1504 __ b(ne, miss); | 1539 __ b(ne, miss); |
1505 } | 1540 } |
1506 } | 1541 } |
1507 | 1542 |
1508 | 1543 |
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 | |
1518 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1544 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1519 Handle<Cell> cell, | 1545 Handle<Cell> cell, |
1520 Handle<JSFunction> function, | 1546 Handle<JSFunction> function, |
1521 Label* miss) { | 1547 Label* miss) { |
1522 // Get the value from the cell. | 1548 // Get the value from the cell. |
1523 __ mov(r3, Operand(cell)); | 1549 __ mov(r3, Operand(cell)); |
1524 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | 1550 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); |
1525 | 1551 |
1526 // Check that the cell contains the same function. | 1552 // Check that the cell contains the same function. |
1527 if (heap()->InNewSpace(*function)) { | 1553 if (heap()->InNewSpace(*function)) { |
1528 // We can't embed a pointer to a function in new space so we have | 1554 // We can't embed a pointer to a function in new space so we have |
1529 // to verify that the shared function info is unchanged. This has | 1555 // to verify that the shared function info is unchanged. This has |
1530 // the nice side effect that multiple closures based on the same | 1556 // the nice side effect that multiple closures based on the same |
1531 // function can all use this call IC. Before we load through the | 1557 // function can all use this call IC. Before we load through the |
1532 // function, we have to verify that it still is a function. | 1558 // function, we have to verify that it still is a function. |
1533 GenerateFunctionCheck(r1, r3, miss); | 1559 __ JumpIfSmi(r1, miss); |
| 1560 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 1561 __ b(ne, miss); |
1534 | 1562 |
1535 // Check the shared function info. Make sure it hasn't changed. | 1563 // Check the shared function info. Make sure it hasn't changed. |
1536 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1564 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
1537 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1565 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1538 __ cmp(r4, r3); | 1566 __ cmp(r4, r3); |
1539 } else { | 1567 } else { |
1540 __ cmp(r1, Operand(function)); | 1568 __ cmp(r1, Operand(function)); |
1541 } | 1569 } |
1542 __ b(ne, miss); | 1570 __ b(ne, miss); |
1543 } | 1571 } |
(...skipping 11 matching lines...) Expand all Loading... |
1555 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1583 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1556 Handle<JSObject> holder, | 1584 Handle<JSObject> holder, |
1557 PropertyIndex index, | 1585 PropertyIndex index, |
1558 Handle<Name> name) { | 1586 Handle<Name> name) { |
1559 Label miss; | 1587 Label miss; |
1560 | 1588 |
1561 Register reg = HandlerFrontendHeader( | 1589 Register reg = HandlerFrontendHeader( |
1562 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1590 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1563 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | 1591 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), |
1564 index.translate(holder), Representation::Tagged()); | 1592 index.translate(holder), Representation::Tagged()); |
1565 GenerateJumpFunction(object, r1, &miss); | 1593 |
| 1594 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
1566 | 1595 |
1567 HandlerFrontendFooter(&miss); | 1596 HandlerFrontendFooter(&miss); |
1568 | 1597 |
1569 // Return the generated code. | 1598 // Return the generated code. |
1570 return GetCode(Code::FAST, name); | 1599 return GetCode(Code::FAST, name); |
1571 } | 1600 } |
1572 | 1601 |
1573 | 1602 |
1574 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1603 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1575 Handle<Object> object, | 1604 Handle<Object> object, |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1970 if (index_out_of_range.is_linked()) { | 1999 if (index_out_of_range.is_linked()) { |
1971 __ bind(&index_out_of_range); | 2000 __ bind(&index_out_of_range); |
1972 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 2001 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
1973 __ Drop(argc + 1); | 2002 __ Drop(argc + 1); |
1974 __ Ret(); | 2003 __ Ret(); |
1975 } | 2004 } |
1976 | 2005 |
1977 __ bind(&miss); | 2006 __ bind(&miss); |
1978 // Restore function name in r2. | 2007 // Restore function name in r2. |
1979 __ Move(r2, name); | 2008 __ Move(r2, name); |
1980 HandlerFrontendFooter(&name_miss); | 2009 __ bind(&name_miss); |
| 2010 GenerateMissBranch(); |
1981 | 2011 |
1982 // Return the generated code. | 2012 // Return the generated code. |
1983 return GetCode(type, name); | 2013 return GetCode(type, name); |
1984 } | 2014 } |
1985 | 2015 |
1986 | 2016 |
1987 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2017 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
1988 Handle<Object> object, | 2018 Handle<Object> object, |
1989 Handle<JSObject> holder, | 2019 Handle<JSObject> holder, |
1990 Handle<Cell> cell, | 2020 Handle<Cell> cell, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2036 if (index_out_of_range.is_linked()) { | 2066 if (index_out_of_range.is_linked()) { |
2037 __ bind(&index_out_of_range); | 2067 __ bind(&index_out_of_range); |
2038 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 2068 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
2039 __ Drop(argc + 1); | 2069 __ Drop(argc + 1); |
2040 __ Ret(); | 2070 __ Ret(); |
2041 } | 2071 } |
2042 | 2072 |
2043 __ bind(&miss); | 2073 __ bind(&miss); |
2044 // Restore function name in r2. | 2074 // Restore function name in r2. |
2045 __ Move(r2, name); | 2075 __ Move(r2, name); |
2046 HandlerFrontendFooter(&name_miss); | 2076 __ bind(&name_miss); |
| 2077 GenerateMissBranch(); |
2047 | 2078 |
2048 // Return the generated code. | 2079 // Return the generated code. |
2049 return GetCode(type, name); | 2080 return GetCode(type, name); |
2050 } | 2081 } |
2051 | 2082 |
2052 | 2083 |
2053 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2084 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2054 Handle<Object> object, | 2085 Handle<Object> object, |
2055 Handle<JSObject> holder, | 2086 Handle<JSObject> holder, |
2056 Handle<Cell> cell, | 2087 Handle<Cell> cell, |
(...skipping 26 matching lines...) Expand all Loading... |
2083 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 2114 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
2084 | 2115 |
2085 StringCharFromCodeGenerator generator(code, r0); | 2116 StringCharFromCodeGenerator generator(code, r0); |
2086 generator.GenerateFast(masm()); | 2117 generator.GenerateFast(masm()); |
2087 __ Drop(argc + 1); | 2118 __ Drop(argc + 1); |
2088 __ Ret(); | 2119 __ Ret(); |
2089 | 2120 |
2090 StubRuntimeCallHelper call_helper; | 2121 StubRuntimeCallHelper call_helper; |
2091 generator.GenerateSlow(masm(), call_helper); | 2122 generator.GenerateSlow(masm(), call_helper); |
2092 | 2123 |
| 2124 // Tail call the full function. We do not have to patch the receiver |
| 2125 // because the function makes no use of it. |
2093 __ bind(&slow); | 2126 __ bind(&slow); |
2094 // We do not have to patch the receiver because the function makes no use of | 2127 ParameterCount expected(function); |
2095 // it. | 2128 __ InvokeFunction(function, expected, arguments(), |
2096 GenerateJumpFunctionIgnoreReceiver(function); | 2129 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2097 | 2130 |
2098 HandlerFrontendFooter(&miss); | 2131 HandlerFrontendFooter(&miss); |
2099 | 2132 |
2100 // Return the generated code. | 2133 // Return the generated code. |
2101 return GetCode(type, name); | 2134 return GetCode(type, name); |
2102 } | 2135 } |
2103 | 2136 |
2104 | 2137 |
2105 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2138 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2106 Handle<Object> object, | 2139 Handle<Object> object, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2174 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. | 2207 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. |
2175 // If result doesn't fit into an smi, branch to slow. | 2208 // If result doesn't fit into an smi, branch to slow. |
2176 __ SmiTag(r0, SetCC); | 2209 __ SmiTag(r0, SetCC); |
2177 __ b(vs, &slow); | 2210 __ b(vs, &slow); |
2178 | 2211 |
2179 __ bind(&just_return); | 2212 __ bind(&just_return); |
2180 __ Drop(argc + 1); | 2213 __ Drop(argc + 1); |
2181 __ Ret(); | 2214 __ Ret(); |
2182 | 2215 |
2183 __ bind(&slow); | 2216 __ bind(&slow); |
2184 // We do not have to patch the receiver because the function makes no use of | 2217 // Tail call the full function. We do not have to patch the receiver |
2185 // it. | 2218 // because the function makes no use of it. |
2186 GenerateJumpFunctionIgnoreReceiver(function); | 2219 ParameterCount expected(function); |
| 2220 __ InvokeFunction(function, expected, arguments(), |
| 2221 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2187 | 2222 |
2188 HandlerFrontendFooter(&miss); | 2223 HandlerFrontendFooter(&miss); |
2189 | 2224 |
2190 // Return the generated code. | 2225 // Return the generated code. |
2191 return GetCode(type, name); | 2226 return GetCode(type, name); |
2192 } | 2227 } |
2193 | 2228 |
2194 | 2229 |
2195 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2230 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2196 Handle<Object> object, | 2231 Handle<Object> object, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2254 __ bind(&negative_sign); | 2289 __ bind(&negative_sign); |
2255 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); | 2290 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); |
2256 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2291 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
2257 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 2292 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
2258 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); | 2293 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); |
2259 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 2294 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
2260 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2295 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
2261 __ Drop(argc + 1); | 2296 __ Drop(argc + 1); |
2262 __ Ret(); | 2297 __ Ret(); |
2263 | 2298 |
| 2299 // Tail call the full function. We do not have to patch the receiver |
| 2300 // because the function makes no use of it. |
2264 __ bind(&slow); | 2301 __ bind(&slow); |
2265 // We do not have to patch the receiver because the function makes no use of | 2302 ParameterCount expected(function); |
2266 // it. | 2303 __ InvokeFunction(function, expected, arguments(), |
2267 GenerateJumpFunctionIgnoreReceiver(function); | 2304 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2268 | 2305 |
2269 HandlerFrontendFooter(&miss); | 2306 HandlerFrontendFooter(&miss); |
2270 | 2307 |
2271 // Return the generated code. | 2308 // Return the generated code. |
2272 return GetCode(type, name); | 2309 return GetCode(type, name); |
2273 } | 2310 } |
2274 | 2311 |
2275 | 2312 |
2276 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2313 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2277 const CallOptimization& optimization, | 2314 const CallOptimization& optimization, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2310 // Check that the maps haven't changed and find a Holder as a side effect. | 2347 // Check that the maps haven't changed and find a Holder as a side effect. |
2311 CheckPrototypes( | 2348 CheckPrototypes( |
2312 IC::CurrentTypeOf(object, isolate()), | 2349 IC::CurrentTypeOf(object, isolate()), |
2313 r1, holder, r0, r3, r4, name, depth, &miss); | 2350 r1, holder, r0, r3, r4, name, depth, &miss); |
2314 | 2351 |
2315 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2352 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
2316 | 2353 |
2317 __ bind(&miss); | 2354 __ bind(&miss); |
2318 FreeSpaceForFastApiCall(masm()); | 2355 FreeSpaceForFastApiCall(masm()); |
2319 | 2356 |
2320 HandlerFrontendFooter(&miss_before_stack_reserved); | 2357 __ bind(&miss_before_stack_reserved); |
| 2358 GenerateMissBranch(); |
2321 | 2359 |
2322 // Return the generated code. | 2360 // Return the generated code. |
2323 return GetCode(function); | 2361 return GetCode(function); |
2324 } | 2362 } |
2325 | 2363 |
2326 | 2364 |
2327 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2365 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2328 Label success; | 2366 Label success; |
2329 // Check that the object is a boolean. | 2367 // Check that the object is a boolean. |
2330 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2368 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
2331 __ cmp(object, ip); | 2369 __ cmp(object, ip); |
2332 __ b(eq, &success); | 2370 __ b(eq, &success); |
2333 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2371 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
2334 __ cmp(object, ip); | 2372 __ cmp(object, ip); |
2335 __ b(ne, miss); | 2373 __ b(ne, miss); |
2336 __ bind(&success); | 2374 __ bind(&success); |
2337 } | 2375 } |
2338 | 2376 |
2339 | 2377 |
2340 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2378 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2341 if (!object.is_null() && object->IsGlobalObject()) { | 2379 if (object->IsGlobalObject()) { |
2342 const int argc = arguments().immediate(); | 2380 const int argc = arguments().immediate(); |
2343 const int receiver_offset = argc * kPointerSize; | 2381 const int receiver_offset = argc * kPointerSize; |
2344 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 2382 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
2345 __ str(r3, MemOperand(sp, receiver_offset)); | 2383 __ str(r3, MemOperand(sp, receiver_offset)); |
2346 } | 2384 } |
2347 } | 2385 } |
2348 | 2386 |
2349 | 2387 |
2350 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2388 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2351 Handle<JSObject> holder, | 2389 Handle<JSObject> holder, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2465 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2428 reg = CheckPrototypes( | 2466 reg = CheckPrototypes( |
2429 IC::CurrentTypeOf(prototype, isolate()), | 2467 IC::CurrentTypeOf(prototype, isolate()), |
2430 r1, holder, r1, r3, r4, name, miss); | 2468 r1, holder, r1, r3, r4, name, miss); |
2431 } | 2469 } |
2432 | 2470 |
2433 return reg; | 2471 return reg; |
2434 } | 2472 } |
2435 | 2473 |
2436 | 2474 |
2437 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | 2475 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2438 Register function, | 2476 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2439 Label* miss) { | 2477 ? CALL_AS_FUNCTION |
2440 ASSERT(function.is(r1)); | 2478 : CALL_AS_METHOD; |
2441 // Check that the function really is a function. | 2479 ParameterCount expected(function); |
2442 GenerateFunctionCheck(function, r3, miss); | 2480 __ InvokeFunction(function, expected, arguments(), |
2443 if (!function.is(r1)) __ mov(r1, function); | 2481 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2444 PatchGlobalProxy(object); | |
2445 | |
2446 // Invoke the function. | |
2447 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, | |
2448 NullCallWrapper(), call_kind()); | |
2449 } | 2482 } |
2450 | 2483 |
2451 | 2484 |
| 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 |
2452 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2511 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2453 Handle<JSObject> holder, | 2512 Handle<JSObject> holder, |
2454 Handle<Name> name) { | 2513 Handle<Name> name) { |
2455 Label miss; | 2514 Label miss; |
2456 GenerateNameCheck(name, &miss); | 2515 GenerateNameCheck(name, &miss); |
2457 | 2516 |
2458 // Get the number of arguments. | 2517 // Get the number of arguments. |
2459 const int argc = arguments().immediate(); | 2518 const int argc = arguments().immediate(); |
2460 LookupResult lookup(isolate()); | 2519 LookupResult lookup(isolate()); |
2461 LookupPostInterceptor(holder, name, &lookup); | 2520 LookupPostInterceptor(holder, name, &lookup); |
2462 | 2521 |
2463 // Get the receiver from the stack. | 2522 // Get the receiver from the stack. |
2464 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2523 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2465 | 2524 |
2466 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); | 2525 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); |
2467 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, | 2526 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, |
2468 &miss); | 2527 &miss); |
2469 | 2528 |
2470 // Move returned value, the function to call, to r1. | 2529 // Move returned value, the function to call, to r1. |
2471 __ mov(r1, r0); | 2530 __ mov(r1, r0); |
2472 // Restore receiver. | 2531 // Restore receiver. |
2473 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2532 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
2474 | 2533 |
2475 GenerateJumpFunction(object, r1, &miss); | 2534 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
2476 | 2535 |
2477 HandlerFrontendFooter(&miss); | 2536 // Handle call cache miss. |
| 2537 __ bind(&miss); |
| 2538 GenerateMissBranch(); |
2478 | 2539 |
2479 // Return the generated code. | 2540 // Return the generated code. |
2480 return GetCode(Code::FAST, name); | 2541 return GetCode(Code::FAST, name); |
2481 } | 2542 } |
2482 | 2543 |
2483 | 2544 |
2484 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2545 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2485 Handle<JSObject> object, | 2546 Handle<JSObject> object, |
2486 Handle<GlobalObject> holder, | 2547 Handle<GlobalObject> holder, |
2487 Handle<PropertyCell> cell, | 2548 Handle<PropertyCell> cell, |
2488 Handle<JSFunction> function, | 2549 Handle<JSFunction> function, |
2489 Handle<Name> name) { | 2550 Handle<Name> name) { |
2490 if (HasCustomCallGenerator(function)) { | 2551 if (HasCustomCallGenerator(function)) { |
2491 Handle<Code> code = CompileCustomCall( | 2552 Handle<Code> code = CompileCustomCall( |
2492 object, holder, cell, function, Handle<String>::cast(name), | 2553 object, holder, cell, function, Handle<String>::cast(name), |
2493 Code::NORMAL); | 2554 Code::NORMAL); |
2494 // A null handle means bail out to the regular compiler code below. | 2555 // A null handle means bail out to the regular compiler code below. |
2495 if (!code.is_null()) return code; | 2556 if (!code.is_null()) return code; |
2496 } | 2557 } |
2497 | 2558 |
2498 Label miss; | 2559 Label miss; |
2499 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2560 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2500 // Potentially loads a closure that matches the shared function info of the | |
2501 // function, rather than function. | |
2502 GenerateLoadFunctionFromCell(cell, function, &miss); | 2561 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2562 PatchGlobalProxy(object); |
2503 | 2563 |
| 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). |
2504 Counters* counters = isolate()->counters(); | 2568 Counters* counters = isolate()->counters(); |
2505 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2569 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
2506 GenerateJumpFunction(object, r1, function); | 2570 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 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 |
2507 HandlerFrontendFooter(&miss); | 2581 HandlerFrontendFooter(&miss); |
2508 | 2582 |
2509 // Return the generated code. | 2583 // Return the generated code. |
2510 return GetCode(Code::NORMAL, name); | 2584 return GetCode(Code::NORMAL, name); |
2511 } | 2585 } |
2512 | 2586 |
2513 | 2587 |
2514 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2588 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2515 Handle<JSObject> object, | 2589 Handle<JSObject> object, |
2516 Handle<JSObject> holder, | 2590 Handle<JSObject> holder, |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 // ----------------------------------- | 2962 // ----------------------------------- |
2889 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2963 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2890 } | 2964 } |
2891 | 2965 |
2892 | 2966 |
2893 #undef __ | 2967 #undef __ |
2894 | 2968 |
2895 } } // namespace v8::internal | 2969 } } // namespace v8::internal |
2896 | 2970 |
2897 #endif // V8_TARGET_ARCH_ARM | 2971 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |