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