| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 __ j(not_equal, miss); | 1300 __ j(not_equal, miss); |
| 1301 } else { | 1301 } else { |
| 1302 __ Cmp(rdi, Handle<JSFunction>(function)); | 1302 __ Cmp(rdi, Handle<JSFunction>(function)); |
| 1303 __ j(not_equal, miss); | 1303 __ j(not_equal, miss); |
| 1304 } | 1304 } |
| 1305 } | 1305 } |
| 1306 | 1306 |
| 1307 | 1307 |
| 1308 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1308 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
| 1309 MaybeObject* maybe_obj = | 1309 MaybeObject* maybe_obj = |
| 1310 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1310 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1311 kind_, | 1311 kind_, |
| 1312 extra_ic_state_); | 1312 extra_state_); |
| 1313 Object* obj; | 1313 Object* obj; |
| 1314 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1314 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1315 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1315 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1316 return obj; | 1316 return obj; |
| 1317 } | 1317 } |
| 1318 | 1318 |
| 1319 | 1319 |
| 1320 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, | 1320 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, |
| 1321 JSObject* holder, | 1321 JSObject* holder, |
| 1322 int index, | 1322 int index, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1353 __ j(not_equal, &miss); | 1353 __ j(not_equal, &miss); |
| 1354 | 1354 |
| 1355 // Patch the receiver on the stack with the global proxy if | 1355 // Patch the receiver on the stack with the global proxy if |
| 1356 // necessary. | 1356 // necessary. |
| 1357 if (object->IsGlobalObject()) { | 1357 if (object->IsGlobalObject()) { |
| 1358 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1358 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1359 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1359 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1360 } | 1360 } |
| 1361 | 1361 |
| 1362 // Invoke the function. | 1362 // Invoke the function. |
| 1363 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1363 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1364 ? CALL_AS_FUNCTION | 1364 ? CALL_AS_FUNCTION |
| 1365 : CALL_AS_METHOD; | 1365 : CALL_AS_METHOD; |
| 1366 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 1366 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1367 NullCallWrapper(), call_kind); | 1367 NullCallWrapper(), call_kind); |
| 1368 | 1368 |
| 1369 // Handle call cache miss. | 1369 // Handle call cache miss. |
| 1370 __ bind(&miss); | 1370 __ bind(&miss); |
| 1371 MaybeObject* maybe_result = GenerateMissBranch(); | 1371 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1372 if (maybe_result->IsFailure()) return maybe_result; | 1372 if (maybe_result->IsFailure()) return maybe_result; |
| 1373 | 1373 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1662 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1663 | 1663 |
| 1664 const int argc = arguments().immediate(); | 1664 const int argc = arguments().immediate(); |
| 1665 | 1665 |
| 1666 Label miss; | 1666 Label miss; |
| 1667 Label name_miss; | 1667 Label name_miss; |
| 1668 Label index_out_of_range; | 1668 Label index_out_of_range; |
| 1669 Label* index_out_of_range_label = &index_out_of_range; | 1669 Label* index_out_of_range_label = &index_out_of_range; |
| 1670 | 1670 |
| 1671 if (kind_ == Code::CALL_IC && | 1671 if (kind_ == Code::CALL_IC && |
| 1672 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1672 (CallICBase::StringStubState::decode(extra_state_) == |
| 1673 DEFAULT_STRING_STUB)) { | 1673 DEFAULT_STRING_STUB)) { |
| 1674 index_out_of_range_label = &miss; | 1674 index_out_of_range_label = &miss; |
| 1675 } | 1675 } |
| 1676 | 1676 |
| 1677 GenerateNameCheck(name, &name_miss); | 1677 GenerateNameCheck(name, &name_miss); |
| 1678 | 1678 |
| 1679 // Check that the maps starting from the prototype haven't changed. | 1679 // Check that the maps starting from the prototype haven't changed. |
| 1680 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1680 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1681 Context::STRING_FUNCTION_INDEX, | 1681 Context::STRING_FUNCTION_INDEX, |
| 1682 rax, | 1682 rax, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1746 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); |
| 1747 | 1747 |
| 1748 const int argc = arguments().immediate(); | 1748 const int argc = arguments().immediate(); |
| 1749 | 1749 |
| 1750 Label miss; | 1750 Label miss; |
| 1751 Label name_miss; | 1751 Label name_miss; |
| 1752 Label index_out_of_range; | 1752 Label index_out_of_range; |
| 1753 Label* index_out_of_range_label = &index_out_of_range; | 1753 Label* index_out_of_range_label = &index_out_of_range; |
| 1754 | 1754 |
| 1755 if (kind_ == Code::CALL_IC && | 1755 if (kind_ == Code::CALL_IC && |
| 1756 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1756 (CallICBase::StringStubState::decode(extra_state_) == |
| 1757 DEFAULT_STRING_STUB)) { | 1757 DEFAULT_STRING_STUB)) { |
| 1758 index_out_of_range_label = &miss; | 1758 index_out_of_range_label = &miss; |
| 1759 } | 1759 } |
| 1760 | 1760 |
| 1761 GenerateNameCheck(name, &name_miss); | 1761 GenerateNameCheck(name, &name_miss); |
| 1762 | 1762 |
| 1763 // Check that the maps starting from the prototype haven't changed. | 1763 // Check that the maps starting from the prototype haven't changed. |
| 1764 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1764 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1765 Context::STRING_FUNCTION_INDEX, | 1765 Context::STRING_FUNCTION_INDEX, |
| 1766 rax, | 1766 rax, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 StringCharFromCodeGenerator char_from_code_generator(code, rax); | 1864 StringCharFromCodeGenerator char_from_code_generator(code, rax); |
| 1865 char_from_code_generator.GenerateFast(masm()); | 1865 char_from_code_generator.GenerateFast(masm()); |
| 1866 __ ret(2 * kPointerSize); | 1866 __ ret(2 * kPointerSize); |
| 1867 | 1867 |
| 1868 StubRuntimeCallHelper call_helper; | 1868 StubRuntimeCallHelper call_helper; |
| 1869 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1869 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 1870 | 1870 |
| 1871 // Tail call the full function. We do not have to patch the receiver | 1871 // Tail call the full function. We do not have to patch the receiver |
| 1872 // because the function makes no use of it. | 1872 // because the function makes no use of it. |
| 1873 __ bind(&slow); | 1873 __ bind(&slow); |
| 1874 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1874 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1875 ? CALL_AS_FUNCTION | 1875 ? CALL_AS_FUNCTION |
| 1876 : CALL_AS_METHOD; | 1876 : CALL_AS_METHOD; |
| 1877 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1877 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1878 NullCallWrapper(), call_kind); | 1878 NullCallWrapper(), call_kind); |
| 1879 | 1879 |
| 1880 __ bind(&miss); | 1880 __ bind(&miss); |
| 1881 // rcx: function name. | 1881 // rcx: function name. |
| 1882 MaybeObject* maybe_result = GenerateMissBranch(); | 1882 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1883 if (maybe_result->IsFailure()) return maybe_result; | 1883 if (maybe_result->IsFailure()) return maybe_result; |
| 1884 | 1884 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1981 // number. We still have the sign mask in rdi. | 1981 // number. We still have the sign mask in rdi. |
| 1982 __ bind(&negative_sign); | 1982 __ bind(&negative_sign); |
| 1983 __ xor_(rbx, rdi); | 1983 __ xor_(rbx, rdi); |
| 1984 __ AllocateHeapNumber(rax, rdx, &slow); | 1984 __ AllocateHeapNumber(rax, rdx, &slow); |
| 1985 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 1985 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 1986 __ ret(2 * kPointerSize); | 1986 __ ret(2 * kPointerSize); |
| 1987 | 1987 |
| 1988 // Tail call the full function. We do not have to patch the receiver | 1988 // Tail call the full function. We do not have to patch the receiver |
| 1989 // because the function makes no use of it. | 1989 // because the function makes no use of it. |
| 1990 __ bind(&slow); | 1990 __ bind(&slow); |
| 1991 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1991 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1992 ? CALL_AS_FUNCTION | 1992 ? CALL_AS_FUNCTION |
| 1993 : CALL_AS_METHOD; | 1993 : CALL_AS_METHOD; |
| 1994 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1994 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1995 NullCallWrapper(), call_kind); | 1995 NullCallWrapper(), call_kind); |
| 1996 | 1996 |
| 1997 __ bind(&miss); | 1997 __ bind(&miss); |
| 1998 // rcx: function name. | 1998 // rcx: function name. |
| 1999 MaybeObject* maybe_result = GenerateMissBranch(); | 1999 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2000 if (maybe_result->IsFailure()) return maybe_result; | 2000 if (maybe_result->IsFailure()) return maybe_result; |
| 2001 | 2001 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2179 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2179 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 2180 rbx, rdx, rdi, name, &miss); | 2180 rbx, rdx, rdi, name, &miss); |
| 2181 } | 2181 } |
| 2182 break; | 2182 break; |
| 2183 } | 2183 } |
| 2184 | 2184 |
| 2185 default: | 2185 default: |
| 2186 UNREACHABLE(); | 2186 UNREACHABLE(); |
| 2187 } | 2187 } |
| 2188 | 2188 |
| 2189 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2189 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2190 ? CALL_AS_FUNCTION | 2190 ? CALL_AS_FUNCTION |
| 2191 : CALL_AS_METHOD; | 2191 : CALL_AS_METHOD; |
| 2192 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2192 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2193 NullCallWrapper(), call_kind); | 2193 NullCallWrapper(), call_kind); |
| 2194 | 2194 |
| 2195 // Handle call cache miss. | 2195 // Handle call cache miss. |
| 2196 __ bind(&miss); | 2196 __ bind(&miss); |
| 2197 MaybeObject* maybe_result = GenerateMissBranch(); | 2197 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2198 if (maybe_result->IsFailure()) return maybe_result; | 2198 if (maybe_result->IsFailure()) return maybe_result; |
| 2199 | 2199 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2220 | 2220 |
| 2221 // Get the number of arguments. | 2221 // Get the number of arguments. |
| 2222 const int argc = arguments().immediate(); | 2222 const int argc = arguments().immediate(); |
| 2223 | 2223 |
| 2224 LookupResult lookup(isolate()); | 2224 LookupResult lookup(isolate()); |
| 2225 LookupPostInterceptor(holder, name, &lookup); | 2225 LookupPostInterceptor(holder, name, &lookup); |
| 2226 | 2226 |
| 2227 // Get the receiver from the stack. | 2227 // Get the receiver from the stack. |
| 2228 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2228 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2229 | 2229 |
| 2230 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_); | 2230 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2231 MaybeObject* result = compiler.Compile(masm(), | 2231 MaybeObject* result = compiler.Compile(masm(), |
| 2232 object, | 2232 object, |
| 2233 holder, | 2233 holder, |
| 2234 name, | 2234 name, |
| 2235 &lookup, | 2235 &lookup, |
| 2236 rdx, | 2236 rdx, |
| 2237 rbx, | 2237 rbx, |
| 2238 rdi, | 2238 rdi, |
| 2239 rax, | 2239 rax, |
| 2240 &miss); | 2240 &miss); |
| 2241 if (result->IsFailure()) return result; | 2241 if (result->IsFailure()) return result; |
| 2242 | 2242 |
| 2243 // Restore receiver. | 2243 // Restore receiver. |
| 2244 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2244 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2245 | 2245 |
| 2246 // Check that the function really is a function. | 2246 // Check that the function really is a function. |
| 2247 __ JumpIfSmi(rax, &miss); | 2247 __ JumpIfSmi(rax, &miss); |
| 2248 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2248 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2249 __ j(not_equal, &miss); | 2249 __ j(not_equal, &miss); |
| 2250 | 2250 |
| 2251 // Patch the receiver on the stack with the global proxy if | 2251 // Patch the receiver on the stack with the global proxy if |
| 2252 // necessary. | 2252 // necessary. |
| 2253 if (object->IsGlobalObject()) { | 2253 if (object->IsGlobalObject()) { |
| 2254 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2254 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2255 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2255 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2256 } | 2256 } |
| 2257 | 2257 |
| 2258 // Invoke the function. | 2258 // Invoke the function. |
| 2259 __ movq(rdi, rax); | 2259 __ movq(rdi, rax); |
| 2260 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2260 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2261 ? CALL_AS_FUNCTION | 2261 ? CALL_AS_FUNCTION |
| 2262 : CALL_AS_METHOD; | 2262 : CALL_AS_METHOD; |
| 2263 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2263 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2264 NullCallWrapper(), call_kind); | 2264 NullCallWrapper(), call_kind); |
| 2265 | 2265 |
| 2266 // Handle load cache miss. | 2266 // Handle load cache miss. |
| 2267 __ bind(&miss); | 2267 __ bind(&miss); |
| 2268 MaybeObject* maybe_result = GenerateMissBranch(); | 2268 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2269 if (maybe_result->IsFailure()) return maybe_result; | 2269 if (maybe_result->IsFailure()) return maybe_result; |
| 2270 | 2270 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2313 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2313 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2314 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2314 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2315 } | 2315 } |
| 2316 | 2316 |
| 2317 // Setup the context (function already in rdi). | 2317 // Setup the context (function already in rdi). |
| 2318 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2318 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2319 | 2319 |
| 2320 // Jump to the cached code (tail call). | 2320 // Jump to the cached code (tail call). |
| 2321 Counters* counters = isolate()->counters(); | 2321 Counters* counters = isolate()->counters(); |
| 2322 __ IncrementCounter(counters->call_global_inline(), 1); | 2322 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2323 ASSERT(function->is_compiled()); | |
| 2324 ParameterCount expected(function->shared()->formal_parameter_count()); | 2323 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2325 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2324 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2326 ? CALL_AS_FUNCTION | 2325 ? CALL_AS_FUNCTION |
| 2327 : CALL_AS_METHOD; | 2326 : CALL_AS_METHOD; |
| 2328 if (V8::UseCrankshaft()) { | 2327 // We call indirectly through the code field in the function to |
| 2329 // TODO(kasperl): For now, we always call indirectly through the | 2328 // allow recompilation to take effect without changing any of the |
| 2330 // code field in the function to allow recompilation to take effect | 2329 // call sites. |
| 2331 // without changing any of the call sites. | 2330 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2332 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2331 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2333 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2332 NullCallWrapper(), call_kind); |
| 2334 NullCallWrapper(), call_kind); | 2333 |
| 2335 } else { | |
| 2336 Handle<Code> code(function->code()); | |
| 2337 __ InvokeCode(code, expected, arguments(), | |
| 2338 RelocInfo::CODE_TARGET, JUMP_FUNCTION, | |
| 2339 NullCallWrapper(), call_kind); | |
| 2340 } | |
| 2341 // Handle call cache miss. | 2334 // Handle call cache miss. |
| 2342 __ bind(&miss); | 2335 __ bind(&miss); |
| 2343 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2336 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2344 MaybeObject* maybe_result = GenerateMissBranch(); | 2337 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2345 if (maybe_result->IsFailure()) return maybe_result; | 2338 if (maybe_result->IsFailure()) return maybe_result; |
| 2346 | 2339 |
| 2347 // Return the generated code. | 2340 // Return the generated code. |
| 2348 return GetCode(NORMAL, name); | 2341 return GetCode(NORMAL, name); |
| 2349 } | 2342 } |
| 2350 | 2343 |
| (...skipping 1453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3804 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3797 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3805 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 3798 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 3806 } | 3799 } |
| 3807 | 3800 |
| 3808 | 3801 |
| 3809 #undef __ | 3802 #undef __ |
| 3810 | 3803 |
| 3811 } } // namespace v8::internal | 3804 } } // namespace v8::internal |
| 3812 | 3805 |
| 3813 #endif // V8_TARGET_ARCH_X64 | 3806 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |