OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 2279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 if (!AddressIsDeoptimizedCode()) { | 2290 if (!AddressIsDeoptimizedCode()) { |
2291 set_target(*stub); | 2291 set_target(*stub); |
2292 } | 2292 } |
2293 } | 2293 } |
2294 TRACE_IC("StoreIC", key); | 2294 TRACE_IC("StoreIC", key); |
2295 | 2295 |
2296 return store_handle; | 2296 return store_handle; |
2297 } | 2297 } |
2298 | 2298 |
2299 | 2299 |
2300 bool CallIC::DoCustomHandler(Handle<Object> function, | |
2301 const CallICState& callic_state) { | |
2302 DCHECK(FLAG_use_ic && function->IsJSFunction()); | |
2303 | |
2304 // Are we the array function? | |
2305 Handle<JSFunction> array_function = | |
2306 Handle<JSFunction>(isolate()->native_context()->array_function()); | |
2307 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { | |
2308 // Alter the slot. | |
2309 CallICNexus* nexus = casted_nexus<CallICNexus>(); | |
2310 nexus->ConfigureMonomorphicArray(); | |
2311 | |
2312 // Vector-based ICs have a different calling convention in optimized code | |
2313 // than full code so the correct stub has to be chosen. | |
2314 if (AddressIsOptimizedCode()) { | |
2315 CallIC_ArrayStub stub(isolate(), callic_state); | |
2316 set_target(*stub.GetCode()); | |
2317 } else { | |
2318 CallIC_ArrayTrampolineStub stub(isolate(), callic_state); | |
2319 set_target(*stub.GetCode()); | |
2320 } | |
2321 | |
2322 Handle<String> name; | |
2323 if (array_function->shared()->name()->IsString()) { | |
2324 name = Handle<String>(String::cast(array_function->shared()->name()), | |
2325 isolate()); | |
2326 } | |
2327 TRACE_IC("CallIC", name); | |
2328 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | |
2329 MONOMORPHIC); | |
2330 return true; | |
2331 } | |
2332 return false; | |
2333 } | |
2334 | |
2335 | |
2336 void CallIC::PatchMegamorphic(Handle<Object> function) { | |
2337 CallICState callic_state(target()->extra_ic_state()); | |
2338 | |
2339 // We are going generic. | |
2340 CallICNexus* nexus = casted_nexus<CallICNexus>(); | |
2341 nexus->ConfigureMegamorphic(); | |
2342 | |
2343 // Vector-based ICs have a different calling convention in optimized code | |
2344 // than full code so the correct stub has to be chosen. | |
2345 if (AddressIsOptimizedCode()) { | |
2346 CallICStub stub(isolate(), callic_state); | |
2347 set_target(*stub.GetCode()); | |
2348 } else { | |
2349 CallICTrampolineStub stub(isolate(), callic_state); | |
2350 set_target(*stub.GetCode()); | |
2351 } | |
2352 | |
2353 Handle<Object> name = isolate()->factory()->empty_string(); | |
2354 if (function->IsJSFunction()) { | |
2355 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | |
2356 name = handle(js_function->shared()->name(), isolate()); | |
2357 } | |
2358 | |
2359 TRACE_IC("CallIC", name); | |
2360 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | |
2361 GENERIC); | |
2362 } | |
2363 | |
2364 | |
2365 void CallIC::HandleMiss(Handle<Object> function) { | 2300 void CallIC::HandleMiss(Handle<Object> function) { |
2366 CallICState callic_state(target()->extra_ic_state()); | |
2367 Handle<Object> name = isolate()->factory()->empty_string(); | 2301 Handle<Object> name = isolate()->factory()->empty_string(); |
2368 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2302 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
2369 Object* feedback = nexus->GetFeedback(); | 2303 Object* feedback = nexus->GetFeedback(); |
2370 | 2304 |
2371 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. | 2305 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. |
2372 DCHECK(!feedback->IsSmi()); | 2306 DCHECK(!feedback->IsSmi()); |
2373 | 2307 |
2374 if (feedback->IsWeakCell() || !function->IsJSFunction()) { | 2308 if (feedback->IsWeakCell() || !function->IsJSFunction() || |
| 2309 feedback->IsAllocationSite()) { |
2375 // We are going generic. | 2310 // We are going generic. |
2376 nexus->ConfigureMegamorphic(); | 2311 nexus->ConfigureMegamorphic(); |
2377 } else { | 2312 } else { |
2378 // The feedback is either uninitialized or an allocation site. | 2313 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate())); |
2379 // It might be an allocation site because if we re-compile the full code | 2314 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
2380 // to add deoptimization support, we call with the default call-ic, and | |
2381 // merely need to patch the target to match the feedback. | |
2382 // TODO(mvstanton): the better approach is to dispense with patching | |
2383 // altogether, which is in progress. | |
2384 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || | |
2385 feedback->IsAllocationSite()); | |
2386 | 2315 |
2387 // Do we want to install a custom handler? | 2316 Handle<JSFunction> array_function = |
2388 if (FLAG_use_ic && DoCustomHandler(function, callic_state)) { | 2317 Handle<JSFunction>(isolate()->native_context()->array_function()); |
2389 return; | 2318 if (array_function.is_identical_to(js_function)) { |
| 2319 // Alter the slot. |
| 2320 nexus->ConfigureMonomorphicArray(); |
| 2321 } else { |
| 2322 nexus->ConfigureMonomorphic(js_function); |
2390 } | 2323 } |
2391 | |
2392 nexus->ConfigureMonomorphic(Handle<JSFunction>::cast(function)); | |
2393 } | 2324 } |
2394 | 2325 |
2395 if (function->IsJSFunction()) { | 2326 if (function->IsJSFunction()) { |
2396 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2327 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
2397 name = handle(js_function->shared()->name(), isolate()); | 2328 name = handle(js_function->shared()->name(), isolate()); |
2398 } | 2329 } |
2399 | 2330 |
2400 IC::State new_state = nexus->StateFromFeedback(); | 2331 IC::State new_state = nexus->StateFromFeedback(); |
2401 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); | 2332 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); |
2402 TRACE_IC("CallIC", name); | 2333 TRACE_IC("CallIC", name); |
(...skipping 16 matching lines...) Expand all Loading... |
2419 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); | 2350 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); |
2420 Handle<Smi> slot = args.at<Smi>(2); | 2351 Handle<Smi> slot = args.at<Smi>(2); |
2421 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2352 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
2422 CallICNexus nexus(vector, vector_slot); | 2353 CallICNexus nexus(vector, vector_slot); |
2423 CallIC ic(isolate, &nexus); | 2354 CallIC ic(isolate, &nexus); |
2424 ic.HandleMiss(function); | 2355 ic.HandleMiss(function); |
2425 return *function; | 2356 return *function; |
2426 } | 2357 } |
2427 | 2358 |
2428 | 2359 |
2429 RUNTIME_FUNCTION(Runtime_CallIC_Customization_Miss) { | |
2430 TimerEventScope<TimerEventIcMiss> timer(isolate); | |
2431 HandleScope scope(isolate); | |
2432 DCHECK(args.length() == 3); | |
2433 Handle<Object> function = args.at<Object>(0); | |
2434 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); | |
2435 Handle<Smi> slot = args.at<Smi>(2); | |
2436 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | |
2437 CallICNexus nexus(vector, vector_slot); | |
2438 // A miss on a custom call ic always results in going megamorphic. | |
2439 CallIC ic(isolate, &nexus); | |
2440 ic.PatchMegamorphic(function); | |
2441 return *function; | |
2442 } | |
2443 | |
2444 | |
2445 // Used from ic-<arch>.cc. | 2360 // Used from ic-<arch>.cc. |
2446 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) { | 2361 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) { |
2447 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2362 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2448 HandleScope scope(isolate); | 2363 HandleScope scope(isolate); |
2449 Handle<Object> receiver = args.at<Object>(0); | 2364 Handle<Object> receiver = args.at<Object>(0); |
2450 Handle<Name> key = args.at<Name>(1); | 2365 Handle<Name> key = args.at<Name>(1); |
2451 Handle<Object> result; | 2366 Handle<Object> result; |
2452 | 2367 |
2453 DCHECK(args.length() == 4); | 2368 DCHECK(args.length() == 4); |
2454 Handle<Smi> slot = args.at<Smi>(2); | 2369 Handle<Smi> slot = args.at<Smi>(2); |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3208 KeyedLoadICNexus nexus(vector, vector_slot); | 3123 KeyedLoadICNexus nexus(vector, vector_slot); |
3209 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3124 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
3210 ic.UpdateState(receiver, key); | 3125 ic.UpdateState(receiver, key); |
3211 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 3126 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
3212 } | 3127 } |
3213 | 3128 |
3214 return *result; | 3129 return *result; |
3215 } | 3130 } |
3216 } // namespace internal | 3131 } // namespace internal |
3217 } // namespace v8 | 3132 } // namespace v8 |
OLD | NEW |