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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 return; | 241 return; |
242 } | 242 } |
243 | 243 |
244 object = proto; | 244 object = proto; |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 | 248 |
249 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 249 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
250 Handle<String> name) { | 250 Handle<String> name) { |
251 if (target()->is_keyed_stub()) { | 251 ASSERT(IsNameCompatibleWithMonomorphicPrototypeFailure(name)); |
252 // Determine whether the failure is due to a name failure. | |
253 if (!name->IsName()) return false; | |
254 Name* stub_name = target()->FindFirstName(); | |
255 if (*name != stub_name) return false; | |
256 } | |
257 | |
258 InlineCacheHolderFlag cache_holder = | 252 InlineCacheHolderFlag cache_holder = |
259 Code::ExtractCacheHolderFromFlags(target()->flags()); | 253 Code::ExtractCacheHolderFromFlags(target()->flags()); |
260 | 254 |
261 switch (cache_holder) { | 255 switch (cache_holder) { |
262 case OWN_MAP: | 256 case OWN_MAP: |
263 // The stub was generated for JSObject but called for non-JSObject. | 257 // The stub was generated for JSObject but called for non-JSObject. |
264 // IC::GetCodeCacheHolder is not applicable. | 258 // IC::GetCodeCacheHolder is not applicable. |
265 if (!receiver->IsJSObject()) return false; | 259 if (!receiver->IsJSObject()) return false; |
266 break; | 260 break; |
267 case PROTOTYPE_MAP: | 261 case PROTOTYPE_MAP: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 Handle<Code> handler = handlers.at(i); | 323 Handle<Code> handler = handlers.at(i); |
330 int index = map->IndexInCodeCache(*name, *handler); | 324 int index = map->IndexInCodeCache(*name, *handler); |
331 if (index >= 0) { | 325 if (index >= 0) { |
332 map->RemoveFromCodeCache(*name, *handler, index); | 326 map->RemoveFromCodeCache(*name, *handler, index); |
333 return; | 327 return; |
334 } | 328 } |
335 } | 329 } |
336 } | 330 } |
337 | 331 |
338 | 332 |
333 bool IC::IsNameCompatibleWithMonomorphicPrototypeFailure(Handle<Object> name) { | |
334 if (target()->is_keyed_stub()) { | |
335 // Determine whether the failure is due to a name failure. | |
336 if (!name->IsName()) return false; | |
337 Name* stub_name = target()->FindFirstName(); | |
338 if (*name != stub_name) return false; | |
339 } | |
340 | |
341 return true; | |
342 } | |
343 | |
344 | |
339 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { | 345 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { |
340 if (!name->IsString()) return; | 346 if (!name->IsString()) return; |
341 if (state() != MONOMORPHIC) { | 347 if (state() != MONOMORPHIC) { |
342 if (state() == POLYMORPHIC && receiver->IsHeapObject()) { | 348 if (state() == POLYMORPHIC && receiver->IsHeapObject()) { |
343 TryRemoveInvalidHandlers( | 349 TryRemoveInvalidHandlers( |
344 handle(Handle<HeapObject>::cast(receiver)->map()), | 350 handle(Handle<HeapObject>::cast(receiver)->map()), |
345 Handle<String>::cast(name)); | 351 Handle<String>::cast(name)); |
346 } | 352 } |
347 return; | 353 return; |
348 } | 354 } |
349 if (receiver->IsUndefined() || receiver->IsNull()) return; | 355 if (receiver->IsUndefined() || receiver->IsNull()) return; |
350 | 356 |
351 // Remove the target from the code cache if it became invalid | 357 // Remove the target from the code cache if it became invalid |
352 // because of changes in the prototype chain to avoid hitting it | 358 // because of changes in the prototype chain to avoid hitting it |
353 // again. | 359 // again. |
354 if (TryRemoveInvalidPrototypeDependentStub( | 360 if (IsNameCompatibleWithMonomorphicPrototypeFailure(name) && |
361 TryRemoveInvalidPrototypeDependentStub( | |
355 receiver, Handle<String>::cast(name))) { | 362 receiver, Handle<String>::cast(name))) { |
356 return MarkMonomorphicPrototypeFailure(); | 363 MarkMonomorphicPrototypeFailure(name); |
364 return; | |
357 } | 365 } |
358 | 366 |
359 // The builtins object is special. It only changes when JavaScript | 367 // The builtins object is special. It only changes when JavaScript |
360 // builtins are loaded lazily. It is important to keep inline | 368 // builtins are loaded lazily. It is important to keep inline |
361 // caches for the builtins object monomorphic. Therefore, if we get | 369 // caches for the builtins object monomorphic. Therefore, if we get |
362 // an inline cache miss for the builtins object after lazily loading | 370 // an inline cache miss for the builtins object after lazily loading |
363 // JavaScript builtins, we return uninitialized as the state to | 371 // JavaScript builtins, we return uninitialized as the state to |
364 // force the inline cache back to monomorphic state. | 372 // force the inline cache back to monomorphic state. |
365 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; | 373 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; |
366 } | 374 } |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1168 PropertyDetails target_details = lookup->GetTransitionDetails(); | 1176 PropertyDetails target_details = lookup->GetTransitionDetails(); |
1169 if (target_details.IsReadOnly()) return false; | 1177 if (target_details.IsReadOnly()) return false; |
1170 | 1178 |
1171 // If the value that's being stored does not fit in the field that the | 1179 // If the value that's being stored does not fit in the field that the |
1172 // instance would transition to, create a new transition that fits the value. | 1180 // instance would transition to, create a new transition that fits the value. |
1173 // This has to be done before generating the IC, since that IC will embed the | 1181 // This has to be done before generating the IC, since that IC will embed the |
1174 // transition target. | 1182 // transition target. |
1175 // Ensure the instance and its map were migrated before trying to update the | 1183 // Ensure the instance and its map were migrated before trying to update the |
1176 // transition target. | 1184 // transition target. |
1177 ASSERT(!receiver->map()->is_deprecated()); | 1185 ASSERT(!receiver->map()->is_deprecated()); |
1186 | |
1187 if (!ic->IsNameCompatibleWithMonomorphicPrototypeFailure(name)) return false; | |
Toon Verwaest
2014/03/31 12:34:44
This is not exactly the same...
The name only has
mvstanton
2014/03/31 13:30:57
I ran into an issue with that idea. TryRemoiveInva
| |
1178 if (!value->FitsRepresentation(target_details.representation())) { | 1188 if (!value->FitsRepresentation(target_details.representation())) { |
1179 Handle<Map> target(lookup->GetTransitionTarget()); | 1189 Handle<Map> target(lookup->GetTransitionTarget()); |
1180 Map::GeneralizeRepresentation( | 1190 Map::GeneralizeRepresentation( |
1181 target, target->LastAdded(), | 1191 target, target->LastAdded(), |
1182 value->OptimalRepresentation(), FORCE_FIELD); | 1192 value->OptimalRepresentation(), FORCE_FIELD); |
1183 // Lookup the transition again since the transition tree may have changed | 1193 // Lookup the transition again since the transition tree may have changed |
1184 // entirely by the migration above. | 1194 // entirely by the migration above. |
1185 receiver->map()->LookupTransition(*holder, *name, lookup); | 1195 receiver->map()->LookupTransition(*holder, *name, lookup); |
1186 if (!lookup->IsTransition()) return false; | 1196 if (!lookup->IsTransition()) return false; |
1187 ic->MarkMonomorphicPrototypeFailure(); | 1197 ic->MarkMonomorphicPrototypeFailure(name); |
1188 } | 1198 } |
1189 return true; | 1199 return true; |
1190 } | 1200 } |
1191 | 1201 |
1192 | 1202 |
1193 MaybeObject* StoreIC::Store(Handle<Object> object, | 1203 MaybeObject* StoreIC::Store(Handle<Object> object, |
1194 Handle<String> name, | 1204 Handle<String> name, |
1195 Handle<Object> value, | 1205 Handle<Object> value, |
1196 JSReceiver::StoreFromKeyed store_mode) { | 1206 JSReceiver::StoreFromKeyed store_mode) { |
1197 if (MigrateDeprecated(object) || object->IsJSProxy()) { | 1207 if (MigrateDeprecated(object) || object->IsJSProxy()) { |
(...skipping 1640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2838 #undef ADDR | 2848 #undef ADDR |
2839 }; | 2849 }; |
2840 | 2850 |
2841 | 2851 |
2842 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2852 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2843 return IC_utilities[id]; | 2853 return IC_utilities[id]; |
2844 } | 2854 } |
2845 | 2855 |
2846 | 2856 |
2847 } } // namespace v8::internal | 2857 } } // namespace v8::internal |
OLD | NEW |