| 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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 // receiver itself or changes to one of its prototypes. | 210 // receiver itself or changes to one of its prototypes. |
| 211 // | 211 // |
| 212 // If there are changes to the receiver itself, the map of the | 212 // If there are changes to the receiver itself, the map of the |
| 213 // receiver will have changed and the current target will not be in | 213 // receiver will have changed and the current target will not be in |
| 214 // the receiver map's code cache. Therefore, if the current target | 214 // the receiver map's code cache. Therefore, if the current target |
| 215 // is in the receiver map's code cache, the inline cache failed due | 215 // is in the receiver map's code cache, the inline cache failed due |
| 216 // to prototype check failure. | 216 // to prototype check failure. |
| 217 int index = map->IndexInCodeCache(name, target); | 217 int index = map->IndexInCodeCache(name, target); |
| 218 if (index >= 0) { | 218 if (index >= 0) { |
| 219 map->RemoveFromCodeCache(String::cast(name), target, index); | 219 map->RemoveFromCodeCache(String::cast(name), target, index); |
| 220 // For loads and stores, handlers are stored in addition to the ICs on the | 220 // Handlers are stored in addition to the ICs on the map. Remove those, too. |
| 221 // map. Remove those, too. | 221 Code* handler = target->FindFirstHandler(); |
| 222 if ((target->is_load_stub() || target->is_keyed_load_stub() || | 222 if (handler != NULL) { |
| 223 target->is_store_stub() || target->is_keyed_store_stub()) && | |
| 224 target->type() != Code::NORMAL) { | |
| 225 Code* handler = target->FindFirstCode(); | |
| 226 index = map->IndexInCodeCache(name, handler); | 223 index = map->IndexInCodeCache(name, handler); |
| 227 if (index >= 0) { | 224 if (index >= 0) { |
| 228 map->RemoveFromCodeCache(String::cast(name), handler, index); | 225 map->RemoveFromCodeCache(String::cast(name), handler, index); |
| 229 } | 226 } |
| 230 } | 227 } |
| 231 return true; | 228 return true; |
| 232 } | 229 } |
| 233 | 230 |
| 234 // The stub is not in the cache. We've ruled out all other kinds of failure | 231 // The stub is not in the cache. We've ruled out all other kinds of failure |
| 235 // except for proptotype chain changes, a deprecated map, a map that's | 232 // except for proptotype chain changes, a deprecated map, a map that's |
| (...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 return true; | 990 return true; |
| 994 } | 991 } |
| 995 | 992 |
| 996 | 993 |
| 997 bool IC::UpdatePolymorphicIC(State state, | 994 bool IC::UpdatePolymorphicIC(State state, |
| 998 Handle<HeapObject> receiver, | 995 Handle<HeapObject> receiver, |
| 999 Handle<String> name, | 996 Handle<String> name, |
| 1000 Handle<Code> code, | 997 Handle<Code> code, |
| 1001 StrictModeFlag strict_mode) { | 998 StrictModeFlag strict_mode) { |
| 1002 if (code->kind() != Code::HANDLER) return false; | 999 if (code->kind() != Code::HANDLER) return false; |
| 1003 if (target()->ic_state() == MONOMORPHIC && | |
| 1004 target()->type() == Code::NORMAL) { | |
| 1005 return false; | |
| 1006 } | |
| 1007 | 1000 |
| 1008 MapHandleList receiver_maps; | 1001 MapHandleList receiver_maps; |
| 1009 CodeHandleList handlers; | 1002 CodeHandleList handlers; |
| 1010 | 1003 |
| 1011 int number_of_valid_maps; | 1004 int number_of_valid_maps; |
| 1012 int handler_to_overwrite = -1; | 1005 int handler_to_overwrite = -1; |
| 1013 Handle<Map> new_receiver_map(receiver->map()); | 1006 Handle<Map> new_receiver_map(receiver->map()); |
| 1014 { | 1007 { |
| 1015 DisallowHeapAllocation no_gc; | 1008 DisallowHeapAllocation no_gc; |
| 1016 target()->FindAllMaps(&receiver_maps); | 1009 target()->FindAllMaps(&receiver_maps); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1031 } | 1024 } |
| 1032 } | 1025 } |
| 1033 | 1026 |
| 1034 if (number_of_valid_maps >= 4) return false; | 1027 if (number_of_valid_maps >= 4) return false; |
| 1035 | 1028 |
| 1036 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. | 1029 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. |
| 1037 // In that case, allow the IC to go back monomorphic. | 1030 // In that case, allow the IC to go back monomorphic. |
| 1038 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { | 1031 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { |
| 1039 return false; | 1032 return false; |
| 1040 } | 1033 } |
| 1041 target()->FindAllCode(&handlers, receiver_maps.length()); | 1034 |
| 1035 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { |
| 1036 return false; |
| 1037 } |
| 1042 } | 1038 } |
| 1043 | 1039 |
| 1044 number_of_valid_maps++; | 1040 number_of_valid_maps++; |
| 1045 if (handler_to_overwrite >= 0) { | 1041 if (handler_to_overwrite >= 0) { |
| 1046 handlers.Set(handler_to_overwrite, code); | 1042 handlers.Set(handler_to_overwrite, code); |
| 1047 } else { | 1043 } else { |
| 1048 receiver_maps.Add(new_receiver_map); | 1044 receiver_maps.Add(new_receiver_map); |
| 1049 handlers.Add(code); | 1045 handlers.Add(code); |
| 1050 } | 1046 } |
| 1051 | 1047 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 set_target(*ic); | 1115 set_target(*ic); |
| 1120 } | 1116 } |
| 1121 | 1117 |
| 1122 | 1118 |
| 1123 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1119 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 1124 MapHandleList receiver_maps; | 1120 MapHandleList receiver_maps; |
| 1125 CodeHandleList handlers; | 1121 CodeHandleList handlers; |
| 1126 { | 1122 { |
| 1127 DisallowHeapAllocation no_gc; | 1123 DisallowHeapAllocation no_gc; |
| 1128 target()->FindAllMaps(&receiver_maps); | 1124 target()->FindAllMaps(&receiver_maps); |
| 1129 target()->FindAllCode(&handlers, receiver_maps.length()); | 1125 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; |
| 1130 } | 1126 } |
| 1131 for (int i = 0; i < receiver_maps.length(); i++) { | 1127 for (int i = 0; i < receiver_maps.length(); i++) { |
| 1132 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1128 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
| 1133 } | 1129 } |
| 1134 } | 1130 } |
| 1135 | 1131 |
| 1136 | 1132 |
| 1137 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { | 1133 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
| 1138 DisallowHeapAllocation no_allocation; | 1134 DisallowHeapAllocation no_allocation; |
| 1139 | 1135 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1163 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1159 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 1164 UpdateMonomorphicIC(receiver, code, name, strict_mode); | 1160 UpdateMonomorphicIC(receiver, code, name, strict_mode); |
| 1165 break; | 1161 break; |
| 1166 case MONOMORPHIC: | 1162 case MONOMORPHIC: |
| 1167 // Only move to megamorphic if the target changes. | 1163 // Only move to megamorphic if the target changes. |
| 1168 if (target() != *code) { | 1164 if (target() != *code) { |
| 1169 if (target()->is_load_stub() || target()->is_store_stub()) { | 1165 if (target()->is_load_stub() || target()->is_store_stub()) { |
| 1170 bool is_same_handler = false; | 1166 bool is_same_handler = false; |
| 1171 { | 1167 { |
| 1172 DisallowHeapAllocation no_allocation; | 1168 DisallowHeapAllocation no_allocation; |
| 1173 Code* old_handler = target()->FindFirstCode(); | 1169 Code* old_handler = target()->FindFirstHandler(); |
| 1174 is_same_handler = old_handler == *code; | 1170 is_same_handler = old_handler == *code; |
| 1175 } | 1171 } |
| 1176 if (is_same_handler | 1172 if (is_same_handler |
| 1177 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | 1173 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
| 1178 UpdateMonomorphicIC(receiver, code, name, strict_mode); | 1174 UpdateMonomorphicIC(receiver, code, name, strict_mode); |
| 1179 break; | 1175 break; |
| 1180 } | 1176 } |
| 1181 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { | 1177 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { |
| 1182 break; | 1178 break; |
| 1183 } | 1179 } |
| 1184 | 1180 |
| 1185 if (target()->type() != Code::NORMAL) { | 1181 CopyICToMegamorphicCache(name); |
| 1186 CopyICToMegamorphicCache(name); | |
| 1187 } | |
| 1188 } | 1182 } |
| 1189 | 1183 |
| 1190 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1184 UpdateMegamorphicCache(receiver->map(), *name, *code); |
| 1191 set_target((strict_mode == kStrictMode) | 1185 set_target((strict_mode == kStrictMode) |
| 1192 ? *megamorphic_stub_strict() | 1186 ? *megamorphic_stub_strict() |
| 1193 : *megamorphic_stub()); | 1187 : *megamorphic_stub()); |
| 1194 } | 1188 } |
| 1195 break; | 1189 break; |
| 1196 case MEGAMORPHIC: | 1190 case MEGAMORPHIC: |
| 1197 // Update the stub cache. | 1191 // Update the stub cache. |
| (...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3162 #undef ADDR | 3156 #undef ADDR |
| 3163 }; | 3157 }; |
| 3164 | 3158 |
| 3165 | 3159 |
| 3166 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3160 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3167 return IC_utilities[id]; | 3161 return IC_utilities[id]; |
| 3168 } | 3162 } |
| 3169 | 3163 |
| 3170 | 3164 |
| 3171 } } // namespace v8::internal | 3165 } } // namespace v8::internal |
| OLD | NEW |