OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 } | 617 } |
618 | 618 |
619 | 619 |
620 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, | 620 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
621 Handle<String> name, | 621 Handle<String> name, |
622 Handle<Code> code) { | 622 Handle<Code> code) { |
623 if (!code->is_handler()) return false; | 623 if (!code->is_handler()) return false; |
624 TypeHandleList types; | 624 TypeHandleList types; |
625 CodeHandleList handlers; | 625 CodeHandleList handlers; |
626 | 626 |
627 int number_of_valid_types; | |
628 int handler_to_overwrite = -1; | |
629 | |
630 target()->FindAllTypes(&types); | 627 target()->FindAllTypes(&types); |
631 int number_of_types = types.length(); | 628 int number_of_types = types.length(); |
632 number_of_valid_types = number_of_types; | 629 int deprecated_types = 0; |
| 630 int handler_to_overwrite = -1; |
633 | 631 |
634 for (int i = 0; i < number_of_types; i++) { | 632 for (int i = 0; i < number_of_types; i++) { |
635 Handle<HeapType> current_type = types.at(i); | 633 Handle<HeapType> current_type = types.at(i); |
636 // Filter out deprecated maps to ensure their instances get migrated. | |
637 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { | 634 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { |
638 number_of_valid_types--; | 635 // Filter out deprecated maps to ensure their instances get migrated. |
639 // If the receiver type is already in the polymorphic IC, this indicates | 636 ++deprecated_types; |
640 // there was a prototoype chain failure. In that case, just overwrite the | |
641 // handler. | |
642 } else if (type->IsCurrently(current_type)) { | 637 } else if (type->IsCurrently(current_type)) { |
643 ASSERT(handler_to_overwrite == -1); | 638 // If the receiver type is already in the polymorphic IC, this indicates |
644 number_of_valid_types--; | 639 // there was a prototoype chain failure. In that case, just overwrite the |
| 640 // handler. |
| 641 handler_to_overwrite = i; |
| 642 } else if (handler_to_overwrite == -1 && |
| 643 current_type->IsClass() && |
| 644 type->IsClass() && |
| 645 IsTransitionOfMonomorphicTarget(*current_type->AsClass(), |
| 646 *type->AsClass())) { |
645 handler_to_overwrite = i; | 647 handler_to_overwrite = i; |
646 } | 648 } |
647 } | 649 } |
648 | 650 |
| 651 int number_of_valid_types = |
| 652 number_of_types - deprecated_types - (handler_to_overwrite != -1); |
| 653 |
649 if (number_of_valid_types >= 4) return false; | 654 if (number_of_valid_types >= 4) return false; |
650 if (number_of_types == 0) return false; | 655 if (number_of_types == 0) return false; |
651 if (!target()->FindHandlers(&handlers, types.length())) return false; | 656 if (!target()->FindHandlers(&handlers, types.length())) return false; |
652 | 657 |
653 number_of_valid_types++; | 658 number_of_valid_types++; |
654 if (handler_to_overwrite >= 0) { | 659 if (handler_to_overwrite >= 0) { |
655 handlers.Set(handler_to_overwrite, code); | 660 handlers.Set(handler_to_overwrite, code); |
| 661 if (!type->IsCurrently(types.at(handler_to_overwrite))) { |
| 662 types.Set(handler_to_overwrite, type); |
| 663 } |
656 } else { | 664 } else { |
657 types.Add(type); | 665 types.Add(type); |
658 handlers.Add(code); | 666 handlers.Add(code); |
659 } | 667 } |
660 | 668 |
661 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 669 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
662 kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state()); | 670 kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state()); |
663 set_target(*ic); | 671 set_target(*ic); |
664 return true; | 672 return true; |
665 } | 673 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 TypeHandleList types; | 728 TypeHandleList types; |
721 CodeHandleList handlers; | 729 CodeHandleList handlers; |
722 target()->FindAllTypes(&types); | 730 target()->FindAllTypes(&types); |
723 if (!target()->FindHandlers(&handlers, types.length())) return; | 731 if (!target()->FindHandlers(&handlers, types.length())) return; |
724 for (int i = 0; i < types.length(); i++) { | 732 for (int i = 0; i < types.length(); i++) { |
725 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 733 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
726 } | 734 } |
727 } | 735 } |
728 | 736 |
729 | 737 |
730 bool IC::IsTransitionOfMonomorphicTarget(Handle<HeapType> type) { | 738 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
731 if (!type->IsClass()) return false; | 739 if (source_map == NULL) return true; |
732 Map* receiver_map = *type->AsClass(); | 740 if (target_map == NULL) return false; |
733 Map* current_map = target()->FindFirstMap(); | 741 ElementsKind target_elements_kind = target_map->elements_kind(); |
734 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | |
735 bool more_general_transition = | 742 bool more_general_transition = |
736 IsMoreGeneralElementsKindTransition( | 743 IsMoreGeneralElementsKindTransition( |
737 current_map->elements_kind(), receiver_elements_kind); | 744 source_map->elements_kind(), target_elements_kind); |
738 Map* transitioned_map = more_general_transition | 745 Map* transitioned_map = more_general_transition |
739 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 746 ? source_map->LookupElementsTransitionMap(target_elements_kind) |
740 : NULL; | 747 : NULL; |
741 | 748 |
742 return transitioned_map == receiver_map; | 749 return transitioned_map == target_map; |
743 } | 750 } |
744 | 751 |
745 | 752 |
746 void IC::PatchCache(Handle<HeapType> type, | 753 void IC::PatchCache(Handle<HeapType> type, |
747 Handle<String> name, | 754 Handle<String> name, |
748 Handle<Code> code) { | 755 Handle<Code> code) { |
749 switch (state()) { | 756 switch (state()) { |
750 case UNINITIALIZED: | 757 case UNINITIALIZED: |
751 case PREMONOMORPHIC: | 758 case PREMONOMORPHIC: |
752 case MONOMORPHIC_PROTOTYPE_FAILURE: | 759 case MONOMORPHIC_PROTOTYPE_FAILURE: |
753 UpdateMonomorphicIC(type, code, name); | 760 UpdateMonomorphicIC(type, code, name); |
754 break; | 761 break; |
755 case MONOMORPHIC: { | 762 case MONOMORPHIC: // Fall through. |
756 // For now, call stubs are allowed to rewrite to the same stub. This | |
757 // happens e.g., when the field does not contain a function. | |
758 ASSERT(!target().is_identical_to(code)); | |
759 Code* old_handler = target()->FindFirstHandler(); | |
760 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { | |
761 UpdateMonomorphicIC(type, code, name); | |
762 break; | |
763 } | |
764 // Fall through. | |
765 } | |
766 case POLYMORPHIC: | 763 case POLYMORPHIC: |
767 if (!target()->is_keyed_stub()) { | 764 if (!target()->is_keyed_stub()) { |
768 if (UpdatePolymorphicIC(type, name, code)) break; | 765 if (UpdatePolymorphicIC(type, name, code)) break; |
769 CopyICToMegamorphicCache(name); | 766 CopyICToMegamorphicCache(name); |
770 } | 767 } |
771 set_target(*megamorphic_stub()); | 768 set_target(*megamorphic_stub()); |
772 // Fall through. | 769 // Fall through. |
773 case MEGAMORPHIC: | 770 case MEGAMORPHIC: |
774 UpdateMegamorphicCache(*type, *name, *code); | 771 UpdateMegamorphicCache(*type, *name, *code); |
775 break; | 772 break; |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 KeyedAccessStoreMode old_store_mode = | 1447 KeyedAccessStoreMode old_store_mode = |
1451 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1448 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
1452 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1449 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
1453 if (state() == MONOMORPHIC) { | 1450 if (state() == MONOMORPHIC) { |
1454 Handle<Map> transitioned_receiver_map = receiver_map; | 1451 Handle<Map> transitioned_receiver_map = receiver_map; |
1455 if (IsTransitionStoreMode(store_mode)) { | 1452 if (IsTransitionStoreMode(store_mode)) { |
1456 transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode); | 1453 transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode); |
1457 } | 1454 } |
1458 if ((receiver_map.is_identical_to(previous_receiver_map) && | 1455 if ((receiver_map.is_identical_to(previous_receiver_map) && |
1459 IsTransitionStoreMode(store_mode)) || | 1456 IsTransitionStoreMode(store_mode)) || |
1460 IsTransitionOfMonomorphicTarget( | 1457 IsTransitionOfMonomorphicTarget(*previous_receiver_map, |
1461 MapToType<HeapType>(transitioned_receiver_map, isolate()))) { | 1458 *transitioned_receiver_map)) { |
1462 // If the "old" and "new" maps are in the same elements map family, or | 1459 // If the "old" and "new" maps are in the same elements map family, or |
1463 // if they at least come from the same origin for a transitioning store, | 1460 // if they at least come from the same origin for a transitioning store, |
1464 // stay MONOMORPHIC and use the map for the most generic ElementsKind. | 1461 // stay MONOMORPHIC and use the map for the most generic ElementsKind. |
1465 store_mode = GetNonTransitioningStoreMode(store_mode); | 1462 store_mode = GetNonTransitioningStoreMode(store_mode); |
1466 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1463 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1467 transitioned_receiver_map, strict_mode(), store_mode); | 1464 transitioned_receiver_map, strict_mode(), store_mode); |
1468 } else if (*previous_receiver_map == receiver->map() && | 1465 } else if (*previous_receiver_map == receiver->map() && |
1469 old_store_mode == STANDARD_STORE && | 1466 old_store_mode == STANDARD_STORE && |
1470 (store_mode == STORE_AND_GROW_NO_TRANSITION || | 1467 (store_mode == STORE_AND_GROW_NO_TRANSITION || |
1471 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1468 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
(...skipping 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2837 #undef ADDR | 2834 #undef ADDR |
2838 }; | 2835 }; |
2839 | 2836 |
2840 | 2837 |
2841 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2838 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2842 return IC_utilities[id]; | 2839 return IC_utilities[id]; |
2843 } | 2840 } |
2844 | 2841 |
2845 | 2842 |
2846 } } // namespace v8::internal | 2843 } } // namespace v8::internal |
OLD | NEW |