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 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 } | 408 } |
409 host->set_profiler_ticks(0); | 409 host->set_profiler_ticks(0); |
410 isolate->runtime_profiler()->NotifyICChanged(); | 410 isolate->runtime_profiler()->NotifyICChanged(); |
411 // TODO(2029): When an optimized function is patched, it would | 411 // TODO(2029): When an optimized function is patched, it would |
412 // be nice to propagate the corresponding type information to its | 412 // be nice to propagate the corresponding type information to its |
413 // unoptimized version for the benefit of later inlining. | 413 // unoptimized version for the benefit of later inlining. |
414 } | 414 } |
415 | 415 |
416 | 416 |
417 // static | 417 // static |
418 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host, | 418 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) { |
419 TypeFeedbackVector* vector, State old_state, | |
420 State new_state) { | |
421 if (host->kind() != Code::FUNCTION) return; | 419 if (host->kind() != Code::FUNCTION) return; |
422 | 420 |
423 if (FLAG_type_info_threshold > 0) { | |
424 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. | |
425 int generic_delta = 0; // "Generic" here includes megamorphic. | |
426 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, | |
427 &generic_delta); | |
428 vector->change_ic_with_type_info_count(polymorphic_delta); | |
429 vector->change_ic_generic_count(generic_delta); | |
430 } | |
431 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); | 421 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); |
432 info->change_own_type_change_checksum(); | 422 info->change_own_type_change_checksum(); |
433 host->set_profiler_ticks(0); | 423 host->set_profiler_ticks(0); |
434 isolate->runtime_profiler()->NotifyICChanged(); | 424 isolate->runtime_profiler()->NotifyICChanged(); |
435 // TODO(2029): When an optimized function is patched, it would | 425 // TODO(2029): When an optimized function is patched, it would |
436 // be nice to propagate the corresponding type information to its | 426 // be nice to propagate the corresponding type information to its |
437 // unoptimized version for the benefit of later inlining. | 427 // unoptimized version for the benefit of later inlining. |
438 } | 428 } |
439 | 429 |
440 | 430 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 UNREACHABLE(); | 474 UNREACHABLE(); |
485 } | 475 } |
486 } | 476 } |
487 | 477 |
488 | 478 |
489 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { | 479 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { |
490 if (IsCleared(nexus)) return; | 480 if (IsCleared(nexus)) return; |
491 // Make sure to also clear the map used in inline fast cases. If we | 481 // Make sure to also clear the map used in inline fast cases. If we |
492 // do not clear these maps, cached code can keep objects alive | 482 // do not clear these maps, cached code can keep objects alive |
493 // through the embedded maps. | 483 // through the embedded maps. |
494 State state = nexus->StateFromFeedback(); | |
495 nexus->ConfigurePremonomorphic(); | 484 nexus->ConfigurePremonomorphic(); |
496 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 485 OnTypeFeedbackChanged(isolate, host); |
497 } | 486 } |
498 | 487 |
499 | 488 |
500 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 489 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
501 // Determine our state. | 490 // Determine our state. |
502 Object* feedback = nexus->vector()->Get(nexus->slot()); | 491 Object* feedback = nexus->vector()->Get(nexus->slot()); |
503 State state = nexus->StateFromFeedback(); | 492 State state = nexus->StateFromFeedback(); |
504 | 493 |
505 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 494 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
506 nexus->ConfigureUninitialized(); | 495 nexus->ConfigureUninitialized(); |
507 // The change in state must be processed. | 496 // The change in state must be processed. |
508 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 497 OnTypeFeedbackChanged(isolate, host); |
509 } | 498 } |
510 } | 499 } |
511 | 500 |
512 | 501 |
513 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | 502 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
514 if (IsCleared(nexus)) return; | 503 if (IsCleared(nexus)) return; |
515 State state = nexus->StateFromFeedback(); | |
516 nexus->ConfigurePremonomorphic(); | 504 nexus->ConfigurePremonomorphic(); |
517 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 505 OnTypeFeedbackChanged(isolate, host); |
518 } | 506 } |
519 | 507 |
520 | 508 |
521 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 509 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
522 Address constant_pool) { | 510 Address constant_pool) { |
523 if (IsCleared(target)) return; | 511 if (IsCleared(target)) return; |
524 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, | 512 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, |
525 target->extra_ic_state()); | 513 target->extra_ic_state()); |
526 SetTargetAtAddress(address, code, constant_pool); | 514 SetTargetAtAddress(address, code, constant_pool); |
527 } | 515 } |
528 | 516 |
529 | 517 |
530 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { | 518 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { |
531 if (IsCleared(nexus)) return; | 519 if (IsCleared(nexus)) return; |
532 State state = nexus->StateFromFeedback(); | |
533 nexus->ConfigurePremonomorphic(); | 520 nexus->ConfigurePremonomorphic(); |
534 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 521 OnTypeFeedbackChanged(isolate, host); |
535 } | 522 } |
536 | 523 |
537 | 524 |
538 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 525 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
539 Address constant_pool) { | 526 Address constant_pool) { |
540 if (IsCleared(target)) return; | 527 if (IsCleared(target)) return; |
541 Handle<Code> code = pre_monomorphic_stub( | 528 Handle<Code> code = pre_monomorphic_stub( |
542 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); | 529 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); |
543 SetTargetAtAddress(address, *code, constant_pool); | 530 SetTargetAtAddress(address, *code, constant_pool); |
544 } | 531 } |
545 | 532 |
546 | 533 |
547 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, | 534 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, |
548 KeyedStoreICNexus* nexus) { | 535 KeyedStoreICNexus* nexus) { |
549 if (IsCleared(nexus)) return; | 536 if (IsCleared(nexus)) return; |
550 State state = nexus->StateFromFeedback(); | |
551 nexus->ConfigurePremonomorphic(); | 537 nexus->ConfigurePremonomorphic(); |
552 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 538 OnTypeFeedbackChanged(isolate, host); |
553 } | 539 } |
554 | 540 |
555 | 541 |
556 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, | 542 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, |
557 Address constant_pool) { | 543 Address constant_pool) { |
558 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); | 544 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); |
559 CompareICStub stub(target->stub_key(), isolate); | 545 CompareICStub stub(target->stub_key(), isolate); |
560 // Only clear CompareICs that can retain objects. | 546 // Only clear CompareICs that can retain objects. |
561 if (stub.state() != CompareICState::KNOWN_RECEIVER) return; | 547 if (stub.state() != CompareICState::KNOWN_RECEIVER) return; |
562 SetTargetAtAddress(address, | 548 SetTargetAtAddress(address, |
(...skipping 29 matching lines...) Expand all Loading... |
592 DCHECK(UseVector()); | 578 DCHECK(UseVector()); |
593 if (new_state == PREMONOMORPHIC) { | 579 if (new_state == PREMONOMORPHIC) { |
594 nexus()->ConfigurePremonomorphic(); | 580 nexus()->ConfigurePremonomorphic(); |
595 } else if (new_state == MEGAMORPHIC) { | 581 } else if (new_state == MEGAMORPHIC) { |
596 nexus()->ConfigureMegamorphic(); | 582 nexus()->ConfigureMegamorphic(); |
597 } else { | 583 } else { |
598 UNREACHABLE(); | 584 UNREACHABLE(); |
599 } | 585 } |
600 | 586 |
601 vector_set_ = true; | 587 vector_set_ = true; |
602 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 588 OnTypeFeedbackChanged(isolate(), get_host()); |
603 new_state); | |
604 } | 589 } |
605 | 590 |
606 | 591 |
607 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 592 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
608 Handle<Code> handler) { | 593 Handle<Code> handler) { |
609 DCHECK(UseVector()); | 594 DCHECK(UseVector()); |
610 if (kind() == Code::LOAD_IC) { | 595 if (kind() == Code::LOAD_IC) { |
611 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 596 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
612 nexus->ConfigureMonomorphic(map, handler); | 597 nexus->ConfigureMonomorphic(map, handler); |
613 } else if (kind() == Code::KEYED_LOAD_IC) { | 598 } else if (kind() == Code::KEYED_LOAD_IC) { |
614 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 599 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
615 nexus->ConfigureMonomorphic(name, map, handler); | 600 nexus->ConfigureMonomorphic(name, map, handler); |
616 } else if (kind() == Code::STORE_IC) { | 601 } else if (kind() == Code::STORE_IC) { |
617 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 602 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
618 nexus->ConfigureMonomorphic(map, handler); | 603 nexus->ConfigureMonomorphic(map, handler); |
619 } else { | 604 } else { |
620 DCHECK(kind() == Code::KEYED_STORE_IC); | 605 DCHECK(kind() == Code::KEYED_STORE_IC); |
621 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 606 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
622 nexus->ConfigureMonomorphic(name, map, handler); | 607 nexus->ConfigureMonomorphic(name, map, handler); |
623 } | 608 } |
624 | 609 |
625 vector_set_ = true; | 610 vector_set_ = true; |
626 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 611 OnTypeFeedbackChanged(isolate(), get_host()); |
627 MONOMORPHIC); | |
628 } | 612 } |
629 | 613 |
630 | 614 |
631 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 615 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
632 CodeHandleList* handlers) { | 616 CodeHandleList* handlers) { |
633 DCHECK(UseVector()); | 617 DCHECK(UseVector()); |
634 if (kind() == Code::LOAD_IC) { | 618 if (kind() == Code::LOAD_IC) { |
635 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 619 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
636 nexus->ConfigurePolymorphic(maps, handlers); | 620 nexus->ConfigurePolymorphic(maps, handlers); |
637 } else if (kind() == Code::KEYED_LOAD_IC) { | 621 } else if (kind() == Code::KEYED_LOAD_IC) { |
638 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 622 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
639 nexus->ConfigurePolymorphic(name, maps, handlers); | 623 nexus->ConfigurePolymorphic(name, maps, handlers); |
640 } else if (kind() == Code::STORE_IC) { | 624 } else if (kind() == Code::STORE_IC) { |
641 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 625 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
642 nexus->ConfigurePolymorphic(maps, handlers); | 626 nexus->ConfigurePolymorphic(maps, handlers); |
643 } else { | 627 } else { |
644 DCHECK(kind() == Code::KEYED_STORE_IC); | 628 DCHECK(kind() == Code::KEYED_STORE_IC); |
645 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 629 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
646 nexus->ConfigurePolymorphic(name, maps, handlers); | 630 nexus->ConfigurePolymorphic(name, maps, handlers); |
647 } | 631 } |
648 | 632 |
649 vector_set_ = true; | 633 vector_set_ = true; |
650 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 634 OnTypeFeedbackChanged(isolate(), get_host()); |
651 POLYMORPHIC); | |
652 } | 635 } |
653 | 636 |
654 | 637 |
655 void IC::ConfigureVectorState(MapHandleList* maps, | 638 void IC::ConfigureVectorState(MapHandleList* maps, |
656 MapHandleList* transitioned_maps, | 639 MapHandleList* transitioned_maps, |
657 CodeHandleList* handlers) { | 640 CodeHandleList* handlers) { |
658 DCHECK(UseVector()); | 641 DCHECK(UseVector()); |
659 DCHECK(kind() == Code::KEYED_STORE_IC); | 642 DCHECK(kind() == Code::KEYED_STORE_IC); |
660 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 643 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
661 nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers); | 644 nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers); |
662 | 645 |
663 vector_set_ = true; | 646 vector_set_ = true; |
664 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 647 OnTypeFeedbackChanged(isolate(), get_host()); |
665 POLYMORPHIC); | |
666 } | 648 } |
667 | 649 |
668 | 650 |
669 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 651 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
670 // If the object is undefined or null it's illegal to try to get any | 652 // If the object is undefined or null it's illegal to try to get any |
671 // of its properties; throw a TypeError in that case. | 653 // of its properties; throw a TypeError in that case. |
672 if (object->IsUndefined() || object->IsNull()) { | 654 if (object->IsUndefined() || object->IsNull()) { |
673 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); | 655 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); |
674 } | 656 } |
675 | 657 |
(...skipping 1522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2198 } else { | 2180 } else { |
2199 nexus->ConfigureMonomorphic(js_function); | 2181 nexus->ConfigureMonomorphic(js_function); |
2200 } | 2182 } |
2201 } | 2183 } |
2202 | 2184 |
2203 if (function->IsJSFunction()) { | 2185 if (function->IsJSFunction()) { |
2204 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2186 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
2205 name = handle(js_function->shared()->name(), isolate()); | 2187 name = handle(js_function->shared()->name(), isolate()); |
2206 } | 2188 } |
2207 | 2189 |
2208 IC::State new_state = nexus->StateFromFeedback(); | 2190 OnTypeFeedbackChanged(isolate(), get_host()); |
2209 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); | |
2210 TRACE_IC("CallIC", name); | 2191 TRACE_IC("CallIC", name); |
2211 } | 2192 } |
2212 | 2193 |
2213 | 2194 |
2214 #undef TRACE_IC | 2195 #undef TRACE_IC |
2215 | 2196 |
2216 | 2197 |
2217 // ---------------------------------------------------------------------------- | 2198 // ---------------------------------------------------------------------------- |
2218 // Static IC stub generators. | 2199 // Static IC stub generators. |
2219 // | 2200 // |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2976 KeyedLoadICNexus nexus(vector, vector_slot); | 2957 KeyedLoadICNexus nexus(vector, vector_slot); |
2977 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2958 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
2978 ic.UpdateState(receiver, key); | 2959 ic.UpdateState(receiver, key); |
2979 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2960 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2980 } | 2961 } |
2981 | 2962 |
2982 return *result; | 2963 return *result; |
2983 } | 2964 } |
2984 } // namespace internal | 2965 } // namespace internal |
2985 } // namespace v8 | 2966 } // namespace v8 |
OLD | NEW |