Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 8883011: Implement ICs for constructor calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 name, depth2, miss); 575 name, depth2, miss);
576 } else { 576 } else {
577 // CheckPrototypes has a side effect of fetching a 'holder' 577 // CheckPrototypes has a side effect of fetching a 'holder'
578 // for API (object which is instanceof for the signature). It's 578 // for API (object which is instanceof for the signature). It's
579 // safe to omit it here, as if present, it should be fetched 579 // safe to omit it here, as if present, it should be fetched
580 // by the previous CheckPrototypes. 580 // by the previous CheckPrototypes.
581 ASSERT(depth2 == kInvalidProtoDepth); 581 ASSERT(depth2 == kInvalidProtoDepth);
582 } 582 }
583 583
584 // Invoke function. 584 // Invoke function.
585 ASSERT(!CallICBase::ConstructCall::decode(extra_state_));
585 if (can_do_fast_api_call) { 586 if (can_do_fast_api_call) {
586 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 587 GenerateFastApiCall(masm, optimization, arguments_.immediate());
587 } else { 588 } else {
588 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 589 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
589 ? CALL_AS_FUNCTION 590 ? CALL_AS_FUNCTION
590 : CALL_AS_METHOD; 591 : CALL_AS_METHOD;
591 __ InvokeFunction(optimization.constant_function(), arguments_, 592 __ InvokeFunction(optimization.constant_function(), arguments_,
592 JUMP_FUNCTION, NullCallWrapper(), call_kind); 593 JUMP_FUNCTION, NullCallWrapper(), call_kind);
593 } 594 }
594 595
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 __ j(not_equal, &miss); 1292 __ j(not_equal, &miss);
1292 1293
1293 // Patch the receiver on the stack with the global proxy if 1294 // Patch the receiver on the stack with the global proxy if
1294 // necessary. 1295 // necessary.
1295 if (object->IsGlobalObject()) { 1296 if (object->IsGlobalObject()) {
1296 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1297 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1297 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1298 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1298 } 1299 }
1299 1300
1300 // Invoke the function. 1301 // Invoke the function.
1301 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1302 if (CallICBase::ConstructCall::decode(extra_state_)) {
1302 ? CALL_AS_FUNCTION 1303 __ InvokeConstruct(edi, arguments());
1303 : CALL_AS_METHOD; 1304 } else {
1304 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 1305 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1305 NullCallWrapper(), call_kind); 1306 ? CALL_AS_FUNCTION
1307 : CALL_AS_METHOD;
1308 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1309 NullCallWrapper(), call_kind);
1310 }
1306 1311
1307 // Handle call cache miss. 1312 // Handle call cache miss.
1308 __ bind(&miss); 1313 __ bind(&miss);
1309 GenerateMissBranch(); 1314 GenerateMissBranch();
1310 1315
1311 // Return the generated code. 1316 // Return the generated code.
1312 return GetCode(FIELD, name); 1317 return GetCode(FIELD, name);
1313 } 1318 }
1314 1319
1315 1320
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1800 StringCharFromCodeGenerator generator(code, eax); 1805 StringCharFromCodeGenerator generator(code, eax);
1801 generator.GenerateFast(masm()); 1806 generator.GenerateFast(masm());
1802 __ ret(2 * kPointerSize); 1807 __ ret(2 * kPointerSize);
1803 1808
1804 StubRuntimeCallHelper call_helper; 1809 StubRuntimeCallHelper call_helper;
1805 generator.GenerateSlow(masm(), call_helper); 1810 generator.GenerateSlow(masm(), call_helper);
1806 1811
1807 // Tail call the full function. We do not have to patch the receiver 1812 // Tail call the full function. We do not have to patch the receiver
1808 // because the function makes no use of it. 1813 // because the function makes no use of it.
1809 __ bind(&slow); 1814 __ bind(&slow);
1815 ASSERT(!CallICBase::ConstructCall::decode(extra_state_));
1810 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1816 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1811 ? CALL_AS_FUNCTION 1817 ? CALL_AS_FUNCTION
1812 : CALL_AS_METHOD; 1818 : CALL_AS_METHOD;
1813 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1819 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1814 NullCallWrapper(), call_kind); 1820 NullCallWrapper(), call_kind);
1815 1821
1816 __ bind(&miss); 1822 __ bind(&miss);
1817 // ecx: function name. 1823 // ecx: function name.
1818 GenerateMissBranch(); 1824 GenerateMissBranch();
1819 1825
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 __ ret(2 * kPointerSize); 1939 __ ret(2 * kPointerSize);
1934 1940
1935 // Return the argument (when it's an already round heap number). 1941 // Return the argument (when it's an already round heap number).
1936 __ bind(&already_round); 1942 __ bind(&already_round);
1937 __ mov(eax, Operand(esp, 1 * kPointerSize)); 1943 __ mov(eax, Operand(esp, 1 * kPointerSize));
1938 __ ret(2 * kPointerSize); 1944 __ ret(2 * kPointerSize);
1939 1945
1940 // Tail call the full function. We do not have to patch the receiver 1946 // Tail call the full function. We do not have to patch the receiver
1941 // because the function makes no use of it. 1947 // because the function makes no use of it.
1942 __ bind(&slow); 1948 __ bind(&slow);
1949 ASSERT(!CallICBase::ConstructCall::decode(extra_state_));
1943 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1950 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1944 NullCallWrapper(), CALL_AS_METHOD); 1951 NullCallWrapper(), CALL_AS_METHOD);
1945 1952
1946 __ bind(&miss); 1953 __ bind(&miss);
1947 // ecx: function name. 1954 // ecx: function name.
1948 GenerateMissBranch(); 1955 GenerateMissBranch();
1949 1956
1950 // Return the generated code. 1957 // Return the generated code.
1951 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 1958 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
1952 } 1959 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 __ and_(ebx, ~HeapNumber::kSignMask); 2045 __ and_(ebx, ~HeapNumber::kSignMask);
2039 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2046 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2040 __ AllocateHeapNumber(eax, edi, edx, &slow); 2047 __ AllocateHeapNumber(eax, edi, edx, &slow);
2041 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2048 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2042 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2049 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2043 __ ret(2 * kPointerSize); 2050 __ ret(2 * kPointerSize);
2044 2051
2045 // Tail call the full function. We do not have to patch the receiver 2052 // Tail call the full function. We do not have to patch the receiver
2046 // because the function makes no use of it. 2053 // because the function makes no use of it.
2047 __ bind(&slow); 2054 __ bind(&slow);
2055 ASSERT(!CallICBase::ConstructCall::decode(extra_state_));
2048 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2056 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2049 NullCallWrapper(), CALL_AS_METHOD); 2057 NullCallWrapper(), CALL_AS_METHOD);
2050 2058
2051 __ bind(&miss); 2059 __ bind(&miss);
2052 // ecx: function name. 2060 // ecx: function name.
2053 GenerateMissBranch(); 2061 GenerateMissBranch();
2054 2062
2055 // Return the generated code. 2063 // Return the generated code.
2056 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2064 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2057 } 2065 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 Handle<JSObject>(JSObject::cast(object->GetPrototype())), 2231 Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2224 eax, holder, ebx, edx, edi, name, &miss); 2232 eax, holder, ebx, edx, edi, name, &miss);
2225 } else { 2233 } else {
2226 // Calling non-strict non-builtins with a value as the receiver 2234 // Calling non-strict non-builtins with a value as the receiver
2227 // requires boxing. 2235 // requires boxing.
2228 __ jmp(&miss); 2236 __ jmp(&miss);
2229 } 2237 }
2230 break; 2238 break;
2231 } 2239 }
2232 2240
2233 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2241 if (CallICBase::ConstructCall::decode(extra_state_)) {
2234 ? CALL_AS_FUNCTION 2242 __ InvokeConstruct(function, arguments());
2235 : CALL_AS_METHOD; 2243 } else {
2236 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2244 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2237 NullCallWrapper(), call_kind); 2245 ? CALL_AS_FUNCTION
2246 : CALL_AS_METHOD;
2247 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2248 NullCallWrapper(), call_kind);
2249 }
2238 2250
2239 // Handle call cache miss. 2251 // Handle call cache miss.
2240 __ bind(&miss); 2252 __ bind(&miss);
2241 GenerateMissBranch(); 2253 GenerateMissBranch();
2242 2254
2243 // Return the generated code. 2255 // Return the generated code.
2244 return GetCode(function); 2256 return GetCode(function);
2245 } 2257 }
2246 2258
2247 2259
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 2294
2283 // Patch the receiver on the stack with the global proxy if 2295 // Patch the receiver on the stack with the global proxy if
2284 // necessary. 2296 // necessary.
2285 if (object->IsGlobalObject()) { 2297 if (object->IsGlobalObject()) {
2286 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2298 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2287 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2299 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2288 } 2300 }
2289 2301
2290 // Invoke the function. 2302 // Invoke the function.
2291 __ mov(edi, eax); 2303 __ mov(edi, eax);
2304 ASSERT(!CallICBase::ConstructCall::decode(extra_state_));
2292 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2305 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2293 ? CALL_AS_FUNCTION 2306 ? CALL_AS_FUNCTION
2294 : CALL_AS_METHOD; 2307 : CALL_AS_METHOD;
2295 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 2308 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2296 NullCallWrapper(), call_kind); 2309 NullCallWrapper(), call_kind);
2297 2310
2298 // Handle load cache miss. 2311 // Handle load cache miss.
2299 __ bind(&miss); 2312 __ bind(&miss);
2300 GenerateMissBranch(); 2313 GenerateMissBranch();
2301 2314
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2337 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2350 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2338 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2351 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2339 } 2352 }
2340 2353
2341 // Setup the context (function already in edi). 2354 // Setup the context (function already in edi).
2342 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2355 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2343 2356
2344 // Jump to the cached code (tail call). 2357 // Jump to the cached code (tail call).
2345 Counters* counters = isolate()->counters(); 2358 Counters* counters = isolate()->counters();
2346 __ IncrementCounter(counters->call_global_inline(), 1); 2359 __ IncrementCounter(counters->call_global_inline(), 1);
2347 ParameterCount expected(function->shared()->formal_parameter_count()); 2360 if (CallICBase::ConstructCall::decode(extra_state_)) {
2348 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2361 __ InvokeConstruct(edi, arguments());
2349 ? CALL_AS_FUNCTION 2362 } else {
2350 : CALL_AS_METHOD; 2363 ParameterCount expected(function->shared()->formal_parameter_count());
2351 // We call indirectly through the code field in the function to 2364 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2352 // allow recompilation to take effect without changing any of the 2365 ? CALL_AS_FUNCTION
2353 // call sites. 2366 : CALL_AS_METHOD;
2354 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 2367 // We call indirectly through the code field in the function to
2355 expected, arguments(), JUMP_FUNCTION, 2368 // allow recompilation to take effect without changing any of the
2356 NullCallWrapper(), call_kind); 2369 // call sites.
2370 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2371 expected, arguments(), JUMP_FUNCTION,
2372 NullCallWrapper(), call_kind);
2373 }
2357 2374
2358 // Handle call cache miss. 2375 // Handle call cache miss.
2359 __ bind(&miss); 2376 __ bind(&miss);
2360 __ IncrementCounter(counters->call_global_inline_miss(), 1); 2377 __ IncrementCounter(counters->call_global_inline_miss(), 1);
2361 GenerateMissBranch(); 2378 GenerateMissBranch();
2362 2379
2363 // Return the generated code. 2380 // Return the generated code.
2364 return GetCode(NORMAL, name); 2381 return GetCode(NORMAL, name);
2365 } 2382 }
2366 2383
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after
3845 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3862 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3846 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3863 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3847 } 3864 }
3848 3865
3849 3866
3850 #undef __ 3867 #undef __
3851 3868
3852 } } // namespace v8::internal 3869 } } // namespace v8::internal
3853 3870
3854 #endif // V8_TARGET_ARCH_IA32 3871 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698