| 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 |