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 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 // If there's no appropriate stub we simply avoid updating the caches. | 776 // If there's no appropriate stub we simply avoid updating the caches. |
777 // TODO(verwaest): Install a slow fallback in this case to avoid not learning, | 777 // TODO(verwaest): Install a slow fallback in this case to avoid not learning, |
778 // and deopting Crankshaft code. | 778 // and deopting Crankshaft code. |
779 if (code.is_null()) return; | 779 if (code.is_null()) return; |
780 | 780 |
781 Handle<JSObject> cache_object = object->IsJSObject() | 781 Handle<JSObject> cache_object = object->IsJSObject() |
782 ? Handle<JSObject>::cast(object) | 782 ? Handle<JSObject>::cast(object) |
783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), | 783 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), |
784 isolate()); | 784 isolate()); |
785 | 785 |
786 PatchCache(cache_object, name, code); | 786 PatchCache(handle(Type::CurrentOf(cache_object), isolate()), name, code); |
787 TRACE_IC("CallIC", name); | 787 TRACE_IC("CallIC", name); |
788 } | 788 } |
789 | 789 |
790 | 790 |
791 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, | 791 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, |
792 Handle<Object> key) { | 792 Handle<Object> key) { |
793 if (key->IsInternalizedString()) { | 793 if (key->IsInternalizedString()) { |
794 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); | 794 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); |
795 } | 795 } |
796 | 796 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 if (!receiver_maps->at(current).is_null() && | 960 if (!receiver_maps->at(current).is_null() && |
961 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 961 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
962 return false; | 962 return false; |
963 } | 963 } |
964 } | 964 } |
965 receiver_maps->Add(new_receiver_map); | 965 receiver_maps->Add(new_receiver_map); |
966 return true; | 966 return true; |
967 } | 967 } |
968 | 968 |
969 | 969 |
970 bool IC::UpdatePolymorphicIC(Handle<Object> receiver, | 970 bool IC::UpdatePolymorphicIC(Handle<Type> type, |
971 Handle<String> name, | 971 Handle<String> name, |
972 Handle<Code> code) { | 972 Handle<Code> code) { |
973 if (!code->is_handler()) return false; | 973 if (!code->is_handler()) return false; |
974 MapHandleList receiver_maps; | 974 TypeHandleList types; |
975 CodeHandleList handlers; | 975 CodeHandleList handlers; |
976 | 976 |
977 int number_of_valid_maps; | 977 int number_of_valid_types; |
978 int handler_to_overwrite = -1; | 978 int handler_to_overwrite = -1; |
979 Handle<Map> new_receiver_map(receiver->GetMarkerMap(isolate())); | |
980 | 979 |
981 target()->FindAllMaps(&receiver_maps); | 980 target()->FindAllTypes(&types); |
982 int number_of_maps = receiver_maps.length(); | 981 int number_of_types = types.length(); |
983 number_of_valid_maps = number_of_maps; | 982 number_of_valid_types = number_of_types; |
984 | 983 |
985 for (int i = 0; i < number_of_maps; i++) { | 984 for (int i = 0; i < number_of_types; i++) { |
986 Handle<Map> map = receiver_maps.at(i); | 985 Handle<Type> current_type = types.at(i); |
987 // Filter out deprecated maps to ensure its instances get migrated. | 986 // Filter out deprecated maps to ensure their instances get migrated. |
988 if (map->is_deprecated()) { | 987 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { |
989 number_of_valid_maps--; | 988 number_of_valid_types--; |
990 // If the receiver map is already in the polymorphic IC, this indicates | 989 // If the receiver type is already in the polymorphic IC, this indicates |
991 // there was a prototoype chain failure. In that case, just overwrite the | 990 // there was a prototoype chain failure. In that case, just overwrite the |
992 // handler. | 991 // handler. |
993 } else if (map.is_identical_to(new_receiver_map)) { | 992 } else if (type->Is(current_type)) { |
994 number_of_valid_maps--; | 993 ASSERT(handler_to_overwrite == -1); |
| 994 number_of_valid_types--; |
995 handler_to_overwrite = i; | 995 handler_to_overwrite = i; |
996 } | 996 } |
997 } | 997 } |
998 | 998 |
999 if (number_of_valid_maps >= 4) return false; | 999 if (number_of_valid_types >= 4) return false; |
1000 if (number_of_maps == 0) return false; | 1000 if (number_of_types == 0) return false; |
| 1001 if (!target()->FindHandlers(&handlers, types.length())) return false; |
1001 | 1002 |
1002 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { | 1003 number_of_valid_types++; |
1003 return false; | |
1004 } | |
1005 | |
1006 number_of_valid_maps++; | |
1007 if (handler_to_overwrite >= 0) { | 1004 if (handler_to_overwrite >= 0) { |
1008 handlers.Set(handler_to_overwrite, code); | 1005 handlers.Set(handler_to_overwrite, code); |
1009 } else { | 1006 } else { |
1010 receiver_maps.Add(new_receiver_map); | 1007 types.Add(type); |
1011 handlers.Add(code); | 1008 handlers.Add(code); |
1012 } | 1009 } |
1013 | 1010 |
1014 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1011 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
1015 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); | 1012 &types, &handlers, number_of_valid_types, name, strict_mode()); |
1016 set_target(*ic); | 1013 set_target(*ic); |
1017 return true; | 1014 return true; |
1018 } | 1015 } |
1019 | 1016 |
1020 | 1017 |
1021 void IC::UpdateMonomorphicIC(Handle<Object> receiver, | 1018 Handle<Map> IC::GetMap(Type* type, Isolate* isolate) { |
| 1019 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); |
| 1020 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); |
| 1021 ASSERT(type->IsClass()); |
| 1022 return type->AsClass(); |
| 1023 } |
| 1024 |
| 1025 |
| 1026 Type* IC::GetType(Handle<Map> map) { |
| 1027 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(); |
| 1028 // The only oddballs that can be recorded in ICs are booleans. |
| 1029 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); |
| 1030 return Type::Class(map); |
| 1031 } |
| 1032 |
| 1033 |
| 1034 void IC::UpdateMonomorphicIC(Handle<Type> type, |
1022 Handle<Code> handler, | 1035 Handle<Code> handler, |
1023 Handle<String> name) { | 1036 Handle<String> name) { |
1024 if (!handler->is_handler()) return set_target(*handler); | 1037 if (!handler->is_handler()) return set_target(*handler); |
1025 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1038 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
1026 name, receiver, handler, strict_mode()); | 1039 name, type, handler, strict_mode()); |
1027 set_target(*ic); | 1040 set_target(*ic); |
1028 } | 1041 } |
1029 | 1042 |
1030 | 1043 |
1031 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1044 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
1032 MapHandleList receiver_maps; | 1045 TypeHandleList types; |
1033 CodeHandleList handlers; | 1046 CodeHandleList handlers; |
1034 target()->FindAllMaps(&receiver_maps); | 1047 target()->FindAllTypes(&types); |
1035 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; | 1048 if (!target()->FindHandlers(&handlers, types.length())) return; |
1036 for (int i = 0; i < receiver_maps.length(); i++) { | 1049 for (int i = 0; i < types.length(); i++) { |
1037 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1050 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
1038 } | 1051 } |
1039 } | 1052 } |
1040 | 1053 |
1041 | 1054 |
1042 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { | 1055 bool IC::IsTransitionOfMonomorphicTarget(Type* type) { |
| 1056 if (!type->IsClass()) return false; |
| 1057 Map* receiver_map = *type->AsClass(); |
1043 Map* current_map = target()->FindFirstMap(); | 1058 Map* current_map = target()->FindFirstMap(); |
1044 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 1059 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); |
1045 bool more_general_transition = | 1060 bool more_general_transition = |
1046 IsMoreGeneralElementsKindTransition( | 1061 IsMoreGeneralElementsKindTransition( |
1047 current_map->elements_kind(), receiver_elements_kind); | 1062 current_map->elements_kind(), receiver_elements_kind); |
1048 Map* transitioned_map = more_general_transition | 1063 Map* transitioned_map = more_general_transition |
1049 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1064 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
1050 : NULL; | 1065 : NULL; |
1051 | 1066 |
1052 return transitioned_map == receiver_map; | 1067 return transitioned_map == receiver_map; |
1053 } | 1068 } |
1054 | 1069 |
1055 | 1070 |
1056 void IC::PatchCache(Handle<Object> object, | 1071 void IC::PatchCache(Handle<Type> type, |
1057 Handle<String> name, | 1072 Handle<String> name, |
1058 Handle<Code> code) { | 1073 Handle<Code> code) { |
1059 switch (state()) { | 1074 switch (state()) { |
1060 case UNINITIALIZED: | 1075 case UNINITIALIZED: |
1061 case PREMONOMORPHIC: | 1076 case PREMONOMORPHIC: |
1062 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1077 case MONOMORPHIC_PROTOTYPE_FAILURE: |
1063 UpdateMonomorphicIC(object, code, name); | 1078 UpdateMonomorphicIC(type, code, name); |
1064 break; | 1079 break; |
1065 case MONOMORPHIC: { | 1080 case MONOMORPHIC: { |
1066 // For now, call stubs are allowed to rewrite to the same stub. This | 1081 // For now, call stubs are allowed to rewrite to the same stub. This |
1067 // happens e.g., when the field does not contain a function. | 1082 // happens e.g., when the field does not contain a function. |
1068 ASSERT(target()->is_call_stub() || | 1083 ASSERT(target()->is_call_stub() || |
1069 target()->is_keyed_call_stub() || | 1084 target()->is_keyed_call_stub() || |
1070 !target().is_identical_to(code)); | 1085 !target().is_identical_to(code)); |
1071 Code* old_handler = target()->FindFirstHandler(); | 1086 Code* old_handler = target()->FindFirstHandler(); |
1072 if (old_handler == *code && | 1087 if (old_handler == *code && IsTransitionOfMonomorphicTarget(*type)) { |
1073 IsTransitionedMapOfMonomorphicTarget( | 1088 UpdateMonomorphicIC(type, code, name); |
1074 object->GetMarkerMap(isolate()))) { | |
1075 UpdateMonomorphicIC(object, code, name); | |
1076 break; | 1089 break; |
1077 } | 1090 } |
1078 // Fall through. | 1091 // Fall through. |
1079 } | 1092 } |
1080 case POLYMORPHIC: | 1093 case POLYMORPHIC: |
1081 if (!target()->is_keyed_stub()) { | 1094 if (!target()->is_keyed_stub()) { |
1082 if (UpdatePolymorphicIC(object, name, code)) break; | 1095 if (UpdatePolymorphicIC(type, name, code)) break; |
1083 CopyICToMegamorphicCache(name); | 1096 CopyICToMegamorphicCache(name); |
1084 } | 1097 } |
1085 set_target(*megamorphic_stub()); | 1098 set_target(*megamorphic_stub()); |
1086 // Fall through. | 1099 // Fall through. |
1087 case MEGAMORPHIC: | 1100 case MEGAMORPHIC: |
1088 UpdateMegamorphicCache(object->GetMarkerMap(isolate()), *name, *code); | 1101 UpdateMegamorphicCache(*type, *name, *code); |
1089 break; | 1102 break; |
1090 case DEBUG_STUB: | 1103 case DEBUG_STUB: |
1091 break; | 1104 break; |
1092 case GENERIC: | 1105 case GENERIC: |
1093 UNREACHABLE(); | 1106 UNREACHABLE(); |
1094 break; | 1107 break; |
1095 } | 1108 } |
1096 } | 1109 } |
1097 | 1110 |
1098 | 1111 |
(...skipping 29 matching lines...) Expand all Loading... |
1128 } else if (!lookup->IsProperty()) { | 1141 } else if (!lookup->IsProperty()) { |
1129 if (kind() == Code::LOAD_IC) { | 1142 if (kind() == Code::LOAD_IC) { |
1130 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); | 1143 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); |
1131 } else { | 1144 } else { |
1132 code = slow_stub(); | 1145 code = slow_stub(); |
1133 } | 1146 } |
1134 } else { | 1147 } else { |
1135 code = ComputeHandler(lookup, object, name); | 1148 code = ComputeHandler(lookup, object, name); |
1136 } | 1149 } |
1137 | 1150 |
1138 PatchCache(object, name, code); | 1151 PatchCache(handle(Type::CurrentOf(object), isolate()), name, code); |
1139 TRACE_IC("LoadIC", name); | 1152 TRACE_IC("LoadIC", name); |
1140 } | 1153 } |
1141 | 1154 |
1142 | 1155 |
1143 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1156 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { |
1144 // Cache code holding map should be consistent with | 1157 // Cache code holding map should be consistent with |
1145 // GenerateMonomorphicCacheProbe. | 1158 // GenerateMonomorphicCacheProbe. |
| 1159 Map* map = *GetMap(type, isolate()); |
1146 isolate()->stub_cache()->Set(name, map, code); | 1160 isolate()->stub_cache()->Set(name, map, code); |
1147 } | 1161 } |
1148 | 1162 |
1149 | 1163 |
1150 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 1164 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
1151 Handle<Object> object, | 1165 Handle<Object> object, |
1152 Handle<String> name, | 1166 Handle<String> name, |
1153 Handle<Object> value) { | 1167 Handle<Object> value) { |
1154 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); | 1168 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); |
1155 Handle<HeapObject> stub_holder(GetCodeCacheHolder( | 1169 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 Handle<String> name, | 1605 Handle<String> name, |
1592 Handle<Object> value) { | 1606 Handle<Object> value) { |
1593 ASSERT(!receiver->IsJSGlobalProxy()); | 1607 ASSERT(!receiver->IsJSGlobalProxy()); |
1594 ASSERT(lookup->IsFound()); | 1608 ASSERT(lookup->IsFound()); |
1595 | 1609 |
1596 // These are not cacheable, so we never see such LookupResults here. | 1610 // These are not cacheable, so we never see such LookupResults here. |
1597 ASSERT(!lookup->IsHandler()); | 1611 ASSERT(!lookup->IsHandler()); |
1598 | 1612 |
1599 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1613 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
1600 | 1614 |
1601 PatchCache(receiver, name, code); | 1615 PatchCache(handle(Type::CurrentOf(receiver), isolate()), name, code); |
1602 TRACE_IC("StoreIC", name); | 1616 TRACE_IC("StoreIC", name); |
1603 } | 1617 } |
1604 | 1618 |
1605 | 1619 |
1606 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1620 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
1607 Handle<Object> object, | 1621 Handle<Object> object, |
1608 Handle<String> name, | 1622 Handle<String> name, |
1609 Handle<Object> value, | 1623 Handle<Object> value, |
1610 InlineCacheHolderFlag cache_holder) { | 1624 InlineCacheHolderFlag cache_holder) { |
1611 ASSERT(cache_holder == OWN_MAP); | 1625 ASSERT(cache_holder == OWN_MAP); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1737 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1751 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
1738 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1752 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
1739 if (state() == MONOMORPHIC) { | 1753 if (state() == MONOMORPHIC) { |
1740 // If the "old" and "new" maps are in the same elements map family, stay | 1754 // If the "old" and "new" maps are in the same elements map family, stay |
1741 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1755 // MONOMORPHIC and use the map for the most generic ElementsKind. |
1742 Handle<Map> transitioned_receiver_map = receiver_map; | 1756 Handle<Map> transitioned_receiver_map = receiver_map; |
1743 if (IsTransitionStoreMode(store_mode)) { | 1757 if (IsTransitionStoreMode(store_mode)) { |
1744 transitioned_receiver_map = | 1758 transitioned_receiver_map = |
1745 ComputeTransitionedMap(receiver, store_mode); | 1759 ComputeTransitionedMap(receiver, store_mode); |
1746 } | 1760 } |
1747 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { | 1761 if (IsTransitionOfMonomorphicTarget(GetType(transitioned_receiver_map))) { |
1748 // Element family is the same, use the "worst" case map. | 1762 // Element family is the same, use the "worst" case map. |
1749 store_mode = GetNonTransitioningStoreMode(store_mode); | 1763 store_mode = GetNonTransitioningStoreMode(store_mode); |
1750 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1764 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1751 transitioned_receiver_map, strict_mode(), store_mode); | 1765 transitioned_receiver_map, strict_mode(), store_mode); |
1752 } else if (*previous_receiver_map == receiver->map() && | 1766 } else if (*previous_receiver_map == receiver->map() && |
1753 old_store_mode == STANDARD_STORE && | 1767 old_store_mode == STANDARD_STORE && |
1754 (IsGrowStoreMode(store_mode) || | 1768 (IsGrowStoreMode(store_mode) || |
1755 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1769 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1756 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1770 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1757 // A "normal" IC that handles stores can switch to a version that can | 1771 // A "normal" IC that handles stores can switch to a version that can |
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2754 #undef ADDR | 2768 #undef ADDR |
2755 }; | 2769 }; |
2756 | 2770 |
2757 | 2771 |
2758 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2772 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2759 return IC_utilities[id]; | 2773 return IC_utilities[id]; |
2760 } | 2774 } |
2761 | 2775 |
2762 | 2776 |
2763 } } // namespace v8::internal | 2777 } } // namespace v8::internal |
OLD | NEW |