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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 Object* name) { | 184 Object* name) { |
185 if (target->is_keyed_load_stub() || | 185 if (target->is_keyed_load_stub() || |
186 target->is_keyed_call_stub() || | 186 target->is_keyed_call_stub() || |
187 target->is_keyed_store_stub()) { | 187 target->is_keyed_store_stub()) { |
188 // Determine whether the failure is due to a name failure. | 188 // Determine whether the failure is due to a name failure. |
189 if (!name->IsName()) return false; | 189 if (!name->IsName()) return false; |
190 Name* stub_name = target->FindFirstName(); | 190 Name* stub_name = target->FindFirstName(); |
191 if (Name::cast(name) != stub_name) return false; | 191 if (Name::cast(name) != stub_name) return false; |
192 } | 192 } |
193 | 193 |
194 if (receiver->IsGlobalObject()) { | |
195 if (!name->IsName()) return false; | |
196 Isolate* isolate = target->GetIsolate(); | |
197 LookupResult lookup(isolate); | |
198 GlobalObject* global = GlobalObject::cast(receiver); | |
199 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); | |
200 if (!lookup.IsFound()) return false; | |
201 PropertyCell* cell = global->GetPropertyCell(&lookup); | |
202 return cell->type()->IsConstant(); | |
203 } | |
204 | |
205 InlineCacheHolderFlag cache_holder = | 194 InlineCacheHolderFlag cache_holder = |
206 Code::ExtractCacheHolderFromFlags(target->flags()); | 195 Code::ExtractCacheHolderFromFlags(target->flags()); |
207 | 196 |
208 Isolate* isolate = target->GetIsolate(); | 197 Isolate* isolate = target->GetIsolate(); |
209 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { | 198 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { |
210 // The stub was generated for JSObject but called for non-JSObject. | 199 // The stub was generated for JSObject but called for non-JSObject. |
211 // IC::GetCodeCacheHolder is not applicable. | 200 // IC::GetCodeCacheHolder is not applicable. |
212 return false; | 201 return false; |
213 } else if (cache_holder == PROTOTYPE_MAP && | 202 } else if (cache_holder == PROTOTYPE_MAP && |
214 receiver->GetPrototype(isolate)->IsNull()) { | 203 receiver->GetPrototype(isolate)->IsNull()) { |
(...skipping 20 matching lines...) Expand all Loading... |
235 target->type() != Code::NORMAL) { | 224 target->type() != Code::NORMAL) { |
236 Code* handler = target->FindFirstCode(); | 225 Code* handler = target->FindFirstCode(); |
237 index = map->IndexInCodeCache(name, handler); | 226 index = map->IndexInCodeCache(name, handler); |
238 if (index >= 0) { | 227 if (index >= 0) { |
239 map->RemoveFromCodeCache(String::cast(name), handler, index); | 228 map->RemoveFromCodeCache(String::cast(name), handler, index); |
240 } | 229 } |
241 } | 230 } |
242 return true; | 231 return true; |
243 } | 232 } |
244 | 233 |
| 234 // 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 |
| 236 // different from the one that the stub expects, or a constant global property |
| 237 // that will become mutable. Threat all those situations as prototype failures |
| 238 // (stay monomorphic if possible). |
| 239 |
245 // If the IC is shared between multiple receivers (slow dictionary mode), then | 240 // If the IC is shared between multiple receivers (slow dictionary mode), then |
246 // the map cannot be deprecated and the stub invalidated. | 241 // the map cannot be deprecated and the stub invalidated. |
247 if (cache_holder != OWN_MAP) return false; | 242 if (cache_holder == OWN_MAP) { |
| 243 Map* old_map = target->FindFirstMap(); |
| 244 if (old_map == map) return true; |
| 245 if (old_map != NULL && old_map->is_deprecated()) return true; |
| 246 } |
248 | 247 |
249 // The stub is not in the cache. We've ruled out all other kinds of failure | 248 if (receiver->IsGlobalObject()) { |
250 // except for proptotype chain changes, a deprecated map, or a map that's | 249 if (!name->IsName()) return false; |
251 // different from the one that the stub expects. If the map hasn't changed, | 250 Isolate* isolate = target->GetIsolate(); |
252 // assume it's a prototype failure. Treat deprecated maps in the same way as | 251 LookupResult lookup(isolate); |
253 // prototype failures (stay monomorphic if possible). | 252 GlobalObject* global = GlobalObject::cast(receiver); |
254 Map* old_map = target->FindFirstMap(); | 253 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); |
255 if (old_map == NULL) return false; | 254 if (!lookup.IsFound()) return false; |
256 return old_map == map || old_map->is_deprecated(); | 255 PropertyCell* cell = global->GetPropertyCell(&lookup); |
| 256 return cell->type()->IsConstant(); |
| 257 } |
| 258 |
| 259 return false; |
257 } | 260 } |
258 | 261 |
259 | 262 |
260 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { | 263 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { |
261 IC::State state = target->ic_state(); | 264 IC::State state = target->ic_state(); |
262 | 265 |
263 if (state != MONOMORPHIC || !name->IsString()) return state; | 266 if (state != MONOMORPHIC || !name->IsString()) return state; |
264 if (receiver->IsUndefined() || receiver->IsNull()) return state; | 267 if (receiver->IsUndefined() || receiver->IsNull()) return state; |
265 | 268 |
266 Code::Kind kind = target->kind(); | 269 Code::Kind kind = target->kind(); |
(...skipping 2827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3094 #undef ADDR | 3097 #undef ADDR |
3095 }; | 3098 }; |
3096 | 3099 |
3097 | 3100 |
3098 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3101 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3099 return IC_utilities[id]; | 3102 return IC_utilities[id]; |
3100 } | 3103 } |
3101 | 3104 |
3102 | 3105 |
3103 } } // namespace v8::internal | 3106 } } // namespace v8::internal |
OLD | NEW |