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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 break; | 263 break; |
264 default: | 264 default: |
265 return false; | 265 return false; |
266 } | 266 } |
267 return false; | 267 return false; |
268 } | 268 } |
269 | 269 |
270 | 270 |
271 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 271 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
272 Handle<String> name) { | 272 Handle<String> name) { |
273 DisallowHeapAllocation no_gc; | |
274 | |
275 if (target()->is_call_stub()) { | 273 if (target()->is_call_stub()) { |
276 LookupResult lookup(isolate()); | 274 LookupResult lookup(isolate()); |
277 LookupForRead(receiver, name, &lookup); | 275 LookupForRead(receiver, name, &lookup); |
278 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) { | 276 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) { |
279 return true; | 277 return true; |
280 } | 278 } |
281 } | 279 } |
282 | 280 |
283 if (target()->is_keyed_stub()) { | 281 if (target()->is_keyed_stub()) { |
284 // Determine whether the failure is due to a name failure. | 282 // Determine whether the failure is due to a name failure. |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 Handle<String> name, | 952 Handle<String> name, |
955 Handle<Code> code) { | 953 Handle<Code> code) { |
956 if (!code->is_handler()) return false; | 954 if (!code->is_handler()) return false; |
957 | 955 |
958 MapHandleList receiver_maps; | 956 MapHandleList receiver_maps; |
959 CodeHandleList handlers; | 957 CodeHandleList handlers; |
960 | 958 |
961 int number_of_valid_maps; | 959 int number_of_valid_maps; |
962 int handler_to_overwrite = -1; | 960 int handler_to_overwrite = -1; |
963 Handle<Map> new_receiver_map(receiver->map()); | 961 Handle<Map> new_receiver_map(receiver->map()); |
964 { | |
965 DisallowHeapAllocation no_gc; | |
966 target()->FindAllMaps(&receiver_maps); | |
967 int number_of_maps = receiver_maps.length(); | |
968 number_of_valid_maps = number_of_maps; | |
969 | 962 |
970 for (int i = 0; i < number_of_maps; i++) { | 963 target()->FindAllMaps(&receiver_maps); |
971 Handle<Map> map = receiver_maps.at(i); | 964 int number_of_maps = receiver_maps.length(); |
972 // Filter out deprecated maps to ensure its instances get migrated. | 965 number_of_valid_maps = number_of_maps; |
973 if (map->is_deprecated()) { | |
974 number_of_valid_maps--; | |
975 // If the receiver map is already in the polymorphic IC, this indicates | |
976 // there was a prototoype chain failure. In that case, just overwrite the | |
977 // handler. | |
978 } else if (map.is_identical_to(new_receiver_map)) { | |
979 number_of_valid_maps--; | |
980 handler_to_overwrite = i; | |
981 } | |
982 } | |
983 | 966 |
984 if (number_of_valid_maps >= 4) return false; | 967 for (int i = 0; i < number_of_maps; i++) { |
985 if (number_of_maps == 0) return false; | 968 Handle<Map> map = receiver_maps.at(i); |
986 | 969 // Filter out deprecated maps to ensure its instances get migrated. |
987 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { | 970 if (map->is_deprecated()) { |
988 return false; | 971 number_of_valid_maps--; |
| 972 // If the receiver map is already in the polymorphic IC, this indicates |
| 973 // there was a prototoype chain failure. In that case, just overwrite the |
| 974 // handler. |
| 975 } else if (map.is_identical_to(new_receiver_map)) { |
| 976 number_of_valid_maps--; |
| 977 handler_to_overwrite = i; |
989 } | 978 } |
990 } | 979 } |
991 | 980 |
| 981 if (number_of_valid_maps >= 4) return false; |
| 982 if (number_of_maps == 0) return false; |
| 983 |
| 984 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { |
| 985 return false; |
| 986 } |
| 987 |
992 number_of_valid_maps++; | 988 number_of_valid_maps++; |
993 if (handler_to_overwrite >= 0) { | 989 if (handler_to_overwrite >= 0) { |
994 handlers.Set(handler_to_overwrite, code); | 990 handlers.Set(handler_to_overwrite, code); |
995 } else { | 991 } else { |
996 receiver_maps.Add(new_receiver_map); | 992 receiver_maps.Add(new_receiver_map); |
997 handlers.Add(code); | 993 handlers.Add(code); |
998 } | 994 } |
999 | 995 |
1000 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 996 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
1001 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); | 997 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); |
1002 set_target(*ic); | 998 set_target(*ic); |
1003 return true; | 999 return true; |
1004 } | 1000 } |
1005 | 1001 |
1006 | 1002 |
1007 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, | 1003 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
1008 Handle<Code> handler, | 1004 Handle<Code> handler, |
1009 Handle<String> name) { | 1005 Handle<String> name) { |
1010 if (!handler->is_handler()) return set_target(*handler); | 1006 if (!handler->is_handler()) return set_target(*handler); |
1011 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1007 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
1012 receiver, handler, name, strict_mode()); | 1008 receiver, handler, name, strict_mode()); |
1013 set_target(*ic); | 1009 set_target(*ic); |
1014 } | 1010 } |
1015 | 1011 |
1016 | 1012 |
1017 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1013 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
1018 MapHandleList receiver_maps; | 1014 MapHandleList receiver_maps; |
1019 CodeHandleList handlers; | 1015 CodeHandleList handlers; |
1020 { | 1016 target()->FindAllMaps(&receiver_maps); |
1021 DisallowHeapAllocation no_gc; | 1017 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; |
1022 target()->FindAllMaps(&receiver_maps); | |
1023 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; | |
1024 } | |
1025 for (int i = 0; i < receiver_maps.length(); i++) { | 1018 for (int i = 0; i < receiver_maps.length(); i++) { |
1026 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1019 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
1027 } | 1020 } |
1028 } | 1021 } |
1029 | 1022 |
1030 | 1023 |
1031 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { | 1024 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
1032 DisallowHeapAllocation no_allocation; | |
1033 | |
1034 Map* current_map = target()->FindFirstMap(); | 1025 Map* current_map = target()->FindFirstMap(); |
1035 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 1026 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); |
1036 bool more_general_transition = | 1027 bool more_general_transition = |
1037 IsMoreGeneralElementsKindTransition( | 1028 IsMoreGeneralElementsKindTransition( |
1038 current_map->elements_kind(), receiver_elements_kind); | 1029 current_map->elements_kind(), receiver_elements_kind); |
1039 Map* transitioned_map = more_general_transition | 1030 Map* transitioned_map = more_general_transition |
1040 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1031 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
1041 : NULL; | 1032 : NULL; |
1042 | 1033 |
1043 return transitioned_map == receiver_map; | 1034 return transitioned_map == receiver_map; |
(...skipping 10 matching lines...) Expand all Loading... |
1054 UpdateMonomorphicIC(receiver, code, name); | 1045 UpdateMonomorphicIC(receiver, code, name); |
1055 break; | 1046 break; |
1056 case MONOMORPHIC: | 1047 case MONOMORPHIC: |
1057 // For now, call stubs are allowed to rewrite to the same stub. This | 1048 // For now, call stubs are allowed to rewrite to the same stub. This |
1058 // happens e.g., when the field does not contain a function. | 1049 // happens e.g., when the field does not contain a function. |
1059 ASSERT(target()->is_call_stub() || | 1050 ASSERT(target()->is_call_stub() || |
1060 target()->is_keyed_call_stub() || | 1051 target()->is_keyed_call_stub() || |
1061 !target().is_identical_to(code)); | 1052 !target().is_identical_to(code)); |
1062 if (!target()->is_keyed_stub()) { | 1053 if (!target()->is_keyed_stub()) { |
1063 bool is_same_handler = false; | 1054 bool is_same_handler = false; |
1064 { | 1055 Code* old_handler = target()->FindFirstHandler(); |
1065 DisallowHeapAllocation no_allocation; | 1056 is_same_handler = old_handler == *code; |
1066 Code* old_handler = target()->FindFirstHandler(); | 1057 |
1067 is_same_handler = old_handler == *code; | 1058 if (is_same_handler && |
1068 } | 1059 IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
1069 if (is_same_handler | |
1070 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | |
1071 UpdateMonomorphicIC(receiver, code, name); | 1060 UpdateMonomorphicIC(receiver, code, name); |
1072 break; | 1061 break; |
1073 } | 1062 } |
1074 if (UpdatePolymorphicIC(receiver, name, code)) { | 1063 } |
1075 break; | 1064 // Fall through. |
1076 } | 1065 case POLYMORPHIC: |
1077 | 1066 if (!target()->is_keyed_stub()) { |
| 1067 if (UpdatePolymorphicIC(receiver, name, code)) break; |
1078 CopyICToMegamorphicCache(name); | 1068 CopyICToMegamorphicCache(name); |
1079 } | 1069 } |
1080 | |
1081 UpdateMegamorphicCache(receiver->map(), *name, *code); | |
1082 set_target(*megamorphic_stub()); | 1070 set_target(*megamorphic_stub()); |
1083 break; | 1071 // Fall through. |
1084 case MEGAMORPHIC: | 1072 case MEGAMORPHIC: |
1085 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1073 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1086 break; | 1074 break; |
1087 case POLYMORPHIC: | |
1088 if (target()->is_keyed_stub()) { | |
1089 // When trying to patch a polymorphic keyed stub with anything other | |
1090 // than another polymorphic stub, go generic. | |
1091 set_target(*generic_stub()); | |
1092 } else { | |
1093 if (UpdatePolymorphicIC(receiver, name, code)) { | |
1094 break; | |
1095 } | |
1096 CopyICToMegamorphicCache(name); | |
1097 UpdateMegamorphicCache(receiver->map(), *name, *code); | |
1098 set_target(*megamorphic_stub()); | |
1099 } | |
1100 break; | |
1101 case DEBUG_STUB: | 1075 case DEBUG_STUB: |
1102 break; | 1076 break; |
1103 case GENERIC: | 1077 case GENERIC: |
1104 UNREACHABLE(); | 1078 UNREACHABLE(); |
1105 break; | 1079 break; |
1106 } | 1080 } |
1107 } | 1081 } |
1108 | 1082 |
1109 | 1083 |
1110 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 1084 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
(...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2737 #undef ADDR | 2711 #undef ADDR |
2738 }; | 2712 }; |
2739 | 2713 |
2740 | 2714 |
2741 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2715 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2742 return IC_utilities[id]; | 2716 return IC_utilities[id]; |
2743 } | 2717 } |
2744 | 2718 |
2745 | 2719 |
2746 } } // namespace v8::internal | 2720 } } // namespace v8::internal |
OLD | NEW |