Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/ic.cc

Issue 25548009: Centralize handler caching and probing in ic.cc. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Undo moving fallback IC handling Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 // The stub was generated for JSObject but called for non-JSObject. 293 // The stub was generated for JSObject but called for non-JSObject.
294 // IC::GetCodeCacheHolder is not applicable. 294 // IC::GetCodeCacheHolder is not applicable.
295 if (!receiver->IsJSObject()) return false; 295 if (!receiver->IsJSObject()) return false;
296 break; 296 break;
297 case PROTOTYPE_MAP: 297 case PROTOTYPE_MAP:
298 // IC::GetCodeCacheHolder is not applicable. 298 // IC::GetCodeCacheHolder is not applicable.
299 if (receiver->GetPrototype(isolate())->IsNull()) return false; 299 if (receiver->GetPrototype(isolate())->IsNull()) return false;
300 break; 300 break;
301 } 301 }
302 302
303 Map* map = IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map(); 303 Handle<Map> map(
304 IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map());
304 305
305 // Decide whether the inline cache failed because of changes to the 306 // Decide whether the inline cache failed because of changes to the
306 // receiver itself or changes to one of its prototypes. 307 // receiver itself or changes to one of its prototypes.
307 // 308 //
308 // If there are changes to the receiver itself, the map of the 309 // If there are changes to the receiver itself, the map of the
309 // receiver will have changed and the current target will not be in 310 // receiver will have changed and the current target will not be in
310 // the receiver map's code cache. Therefore, if the current target 311 // the receiver map's code cache. Therefore, if the current target
311 // is in the receiver map's code cache, the inline cache failed due 312 // is in the receiver map's code cache, the inline cache failed due
312 // to prototype check failure. 313 // to prototype check failure.
313 int index = map->IndexInCodeCache(*name, *target()); 314 int index = map->IndexInCodeCache(*name, *target());
314 if (index >= 0) { 315 if (index >= 0) {
315 map->RemoveFromCodeCache(*name, *target(), index); 316 map->RemoveFromCodeCache(*name, *target(), index);
316 // Handlers are stored in addition to the ICs on the map. Remove those, too. 317 // Handlers are stored in addition to the ICs on the map. Remove those, too.
317 Code* handler = target()->FindFirstHandler(); 318 TryRemoveInvalidHandlers(map, name);
318 if (handler != NULL) {
319 index = map->IndexInCodeCache(*name, handler);
320 if (index >= 0) {
321 map->RemoveFromCodeCache(*name, handler, index);
322 }
323 }
324 return true; 319 return true;
325 } 320 }
326 321
327 // The stub is not in the cache. We've ruled out all other kinds of failure 322 // The stub is not in the cache. We've ruled out all other kinds of failure
328 // except for proptotype chain changes, a deprecated map, a map that's 323 // except for proptotype chain changes, a deprecated map, a map that's
329 // different from the one that the stub expects, elements kind changes, or a 324 // different from the one that the stub expects, elements kind changes, or a
330 // constant global property that will become mutable. Threat all those 325 // constant global property that will become mutable. Threat all those
331 // situations as prototype failures (stay monomorphic if possible). 326 // situations as prototype failures (stay monomorphic if possible).
332 327
333 // If the IC is shared between multiple receivers (slow dictionary mode), then 328 // If the IC is shared between multiple receivers (slow dictionary mode), then
334 // the map cannot be deprecated and the stub invalidated. 329 // the map cannot be deprecated and the stub invalidated.
335 if (cache_holder == OWN_MAP) { 330 if (cache_holder == OWN_MAP) {
336 Map* old_map = target()->FindFirstMap(); 331 Map* old_map = target()->FindFirstMap();
337 if (old_map == map) return true; 332 if (old_map == *map) return true;
338 if (old_map != NULL) { 333 if (old_map != NULL) {
339 if (old_map->is_deprecated()) return true; 334 if (old_map->is_deprecated()) return true;
340 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), 335 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
341 map->elements_kind())) { 336 map->elements_kind())) {
342 return true; 337 return true;
343 } 338 }
344 } 339 }
345 } 340 }
346 341
347 if (receiver->IsGlobalObject()) { 342 if (receiver->IsGlobalObject()) {
348 LookupResult lookup(isolate()); 343 LookupResult lookup(isolate());
349 GlobalObject* global = GlobalObject::cast(*receiver); 344 GlobalObject* global = GlobalObject::cast(*receiver);
350 global->LocalLookupRealNamedProperty(*name, &lookup); 345 global->LocalLookupRealNamedProperty(*name, &lookup);
351 if (!lookup.IsFound()) return false; 346 if (!lookup.IsFound()) return false;
352 PropertyCell* cell = global->GetPropertyCell(&lookup); 347 PropertyCell* cell = global->GetPropertyCell(&lookup);
353 return cell->type()->IsConstant(); 348 return cell->type()->IsConstant();
354 } 349 }
355 350
356 return false; 351 return false;
357 } 352 }
358 353
359 354
355 void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
356 CodeHandleList handlers;
357 target()->FindHandlers(&handlers);
358 for (int i = 0; i < handlers.length(); i++) {
359 Handle<Code> handler = handlers.at(i);
360 int index = map->IndexInCodeCache(*name, *handler);
361 if (index >= 0) {
362 map->RemoveFromCodeCache(*name, *handler, index);
363 return;
364 }
365 }
366 }
367
368
360 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { 369 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
361 if (state() != MONOMORPHIC || !name->IsString()) return; 370 if (!name->IsString()) return;
371 if (state() != MONOMORPHIC) {
372 if (state() == POLYMORPHIC && receiver->IsHeapObject()) {
373 TryRemoveInvalidHandlers(
374 handle(Handle<HeapObject>::cast(receiver)->map()),
375 Handle<String>::cast(name));
376 }
377 return;
378 }
362 if (receiver->IsUndefined() || receiver->IsNull()) return; 379 if (receiver->IsUndefined() || receiver->IsNull()) return;
363 380
364 // Remove the target from the code cache if it became invalid 381 // Remove the target from the code cache if it became invalid
365 // because of changes in the prototype chain to avoid hitting it 382 // because of changes in the prototype chain to avoid hitting it
366 // again. 383 // again.
367 if (TryRemoveInvalidPrototypeDependentStub( 384 if (TryRemoveInvalidPrototypeDependentStub(
368 receiver, Handle<String>::cast(name))) { 385 receiver, Handle<String>::cast(name))) {
369 return MarkMonomorphicPrototypeFailure(); 386 return MarkMonomorphicPrototypeFailure();
370 } 387 }
371 388
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 } else { 1132 } else {
1116 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); 1133 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged());
1117 code = stub.GetCode(isolate()); 1134 code = stub.GetCode(isolate());
1118 } 1135 }
1119 } else if (!object->IsJSObject()) { 1136 } else if (!object->IsJSObject()) {
1120 // TODO(jkummerow): It would be nice to support non-JSObjects in 1137 // TODO(jkummerow): It would be nice to support non-JSObjects in
1121 // ComputeLoadHandler, then we wouldn't need to go generic here. 1138 // ComputeLoadHandler, then we wouldn't need to go generic here.
1122 code = slow_stub(); 1139 code = slow_stub();
1123 } else { 1140 } else {
1124 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); 1141 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name);
1125 if (code.is_null()) code = slow_stub();
1126 } 1142 }
1127 1143
1128 PatchCache(receiver, name, code); 1144 PatchCache(receiver, name, code);
1129 TRACE_IC("LoadIC", name); 1145 TRACE_IC("LoadIC", name);
1130 } 1146 }
1131 1147
1132 1148
1133 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { 1149 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
1134 // Cache code holding map should be consistent with 1150 // Cache code holding map should be consistent with
1135 // GenerateMonomorphicCacheProbe. 1151 // GenerateMonomorphicCacheProbe.
1136 isolate()->stub_cache()->Set(name, map, code); 1152 isolate()->stub_cache()->Set(name, map, code);
1137 } 1153 }
1138 1154
1139 1155
1140 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, 1156 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
1141 Handle<JSObject> receiver, 1157 Handle<JSObject> receiver,
1142 Handle<String> name) { 1158 Handle<String> name) {
1143 if (!lookup->IsProperty()) { 1159 if (!lookup->IsProperty()) {
1144 // Nonexistent property. The result is undefined. 1160 return kind() == Code::LOAD_IC
1145 return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver); 1161 ? isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver)
1162 : generic_stub();
1146 } 1163 }
1147 1164
1148 // Compute monomorphic stub. 1165 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1166 name, receiver, kind());
1167 if (!code.is_null()) return code;
1168
1169 code = CompileLoadHandler(lookup, receiver, name);
1170 if (code.is_null()) return slow_stub();
1171
1172 if (code->is_handler() && code->type() != Code::NORMAL) {
1173 HeapObject::UpdateMapCodeCache(receiver, name, code);
1174 }
1175
1176 return code;
1177 }
1178
1179
1180 Handle<Code> LoadIC::CompileLoadHandler(LookupResult* lookup,
1181 Handle<JSObject> receiver,
1182 Handle<String> name) {
1149 Handle<JSObject> holder(lookup->holder()); 1183 Handle<JSObject> holder(lookup->holder());
1150 switch (lookup->type()) { 1184 switch (lookup->type()) {
1151 case FIELD: 1185 case FIELD:
1152 return isolate()->stub_cache()->ComputeLoadField( 1186 return isolate()->stub_cache()->ComputeLoadField(
1153 name, receiver, holder, 1187 name, receiver, holder,
1154 lookup->GetFieldIndex(), lookup->representation()); 1188 lookup->GetFieldIndex(), lookup->representation());
1155 case CONSTANT: { 1189 case CONSTANT: {
1156 Handle<Object> constant(lookup->GetConstant(), isolate()); 1190 Handle<Object> constant(lookup->GetConstant(), isolate());
1157 // TODO(2803): Don't compute a stub for cons strings because they cannot 1191 // TODO(2803): Don't compute a stub for cons strings because they cannot
1158 // be embedded into code. 1192 // be embedded into code.
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 ASSERT(!stub.is_null()); 1383 ASSERT(!stub.is_null());
1350 set_target(*stub); 1384 set_target(*stub);
1351 TRACE_IC("LoadIC", key); 1385 TRACE_IC("LoadIC", key);
1352 } 1386 }
1353 1387
1354 1388
1355 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1389 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1356 } 1390 }
1357 1391
1358 1392
1359 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, 1393 Handle<Code> KeyedLoadIC::CompileLoadHandler(LookupResult* lookup,
1360 Handle<JSObject> receiver, 1394 Handle<JSObject> receiver,
1361 Handle<String> name) { 1395 Handle<String> name) {
1362 // Bail out if we didn't find a result.
1363 if (!lookup->IsProperty()) return Handle<Code>::null();
1364
1365 // Compute a monomorphic stub. 1396 // Compute a monomorphic stub.
1366 Handle<JSObject> holder(lookup->holder(), isolate()); 1397 Handle<JSObject> holder(lookup->holder(), isolate());
1367 switch (lookup->type()) { 1398 switch (lookup->type()) {
1368 case FIELD: 1399 case FIELD:
1369 return isolate()->stub_cache()->ComputeKeyedLoadField( 1400 return isolate()->stub_cache()->ComputeKeyedLoadField(
1370 name, receiver, holder, 1401 name, receiver, holder,
1371 lookup->GetFieldIndex(), lookup->representation()); 1402 lookup->GetFieldIndex(), lookup->representation());
1372 case CONSTANT: { 1403 case CONSTANT: {
1373 Handle<Object> constant(lookup->GetConstant(), isolate()); 1404 Handle<Object> constant(lookup->GetConstant(), isolate());
1374 // TODO(2803): Don't compute a stub for cons strings because they cannot 1405 // TODO(2803): Don't compute a stub for cons strings because they cannot
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 Handle<JSObject> receiver, 1627 Handle<JSObject> receiver,
1597 Handle<String> name, 1628 Handle<String> name,
1598 Handle<Object> value) { 1629 Handle<Object> value) {
1599 ASSERT(!receiver->IsJSGlobalProxy()); 1630 ASSERT(!receiver->IsJSGlobalProxy());
1600 ASSERT(lookup->IsFound()); 1631 ASSERT(lookup->IsFound());
1601 1632
1602 // These are not cacheable, so we never see such LookupResults here. 1633 // These are not cacheable, so we never see such LookupResults here.
1603 ASSERT(!lookup->IsHandler()); 1634 ASSERT(!lookup->IsHandler());
1604 1635
1605 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); 1636 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value);
1606 if (code.is_null()) {
1607 set_target(*generic_stub());
1608 return;
1609 }
1610 1637
1611 PatchCache(receiver, name, code); 1638 PatchCache(receiver, name, code);
1612 TRACE_IC("StoreIC", name); 1639 TRACE_IC("StoreIC", name);
1613 } 1640 }
1614 1641
1615 1642
1616 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup, 1643 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup,
1617 Handle<JSObject> receiver, 1644 Handle<JSObject> receiver,
1618 Handle<String> name, 1645 Handle<String> name,
1619 Handle<Object> value) { 1646 Handle<Object> value) {
1647 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1648 name, receiver, kind(), strict_mode());
1649 if (!code.is_null()) return code;
1650
1651 code = CompileStoreHandler(lookup, receiver, name, value);
1652 if (code.is_null()) return generic_stub();
1653
1654 if (code->is_handler() && code->type() != Code::NORMAL) {
1655 HeapObject::UpdateMapCodeCache(receiver, name, code);
1656 }
1657
1658 return code;
1659 }
1660
1661
1662 Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
1663 Handle<JSObject> receiver,
1664 Handle<String> name,
1665 Handle<Object> value) {
1620 Handle<JSObject> holder(lookup->holder()); 1666 Handle<JSObject> holder(lookup->holder());
1621 switch (lookup->type()) { 1667 switch (lookup->type()) {
1622 case FIELD: 1668 case FIELD:
1623 return isolate()->stub_cache()->ComputeStoreField( 1669 return isolate()->stub_cache()->ComputeStoreField(
1624 name, receiver, lookup, strict_mode()); 1670 name, receiver, lookup, strict_mode());
1625 case NORMAL: 1671 case NORMAL:
1626 if (receiver->IsGlobalObject()) { 1672 if (receiver->IsGlobalObject()) {
1627 // The stub generated for the global object picks the value directly 1673 // The stub generated for the global object picks the value directly
1628 // from the property cell. So the property must be directly on the 1674 // from the property cell. So the property must be directly on the
1629 // global object. 1675 // global object.
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1998 ASSERT(!stub.is_null()); 2044 ASSERT(!stub.is_null());
1999 set_target(*stub); 2045 set_target(*stub);
2000 TRACE_IC("StoreIC", key); 2046 TRACE_IC("StoreIC", key);
2001 } 2047 }
2002 2048
2003 return Runtime::SetObjectPropertyOrFail( 2049 return Runtime::SetObjectPropertyOrFail(
2004 isolate(), object , key, value, NONE, strict_mode()); 2050 isolate(), object , key, value, NONE, strict_mode());
2005 } 2051 }
2006 2052
2007 2053
2008 Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup, 2054 Handle<Code> KeyedStoreIC::CompileStoreHandler(LookupResult* lookup,
2009 Handle<JSObject> receiver, 2055 Handle<JSObject> receiver,
2010 Handle<String> name, 2056 Handle<String> name,
2011 Handle<Object> value) { 2057 Handle<Object> value) {
2012 // If the property has a non-field type allowing map transitions 2058 // If the property has a non-field type allowing map transitions
2013 // where there is extra room in the object, we leave the IC in its 2059 // where there is extra room in the object, we leave the IC in its
2014 // current state. 2060 // current state.
2015 switch (lookup->type()) { 2061 switch (lookup->type()) {
2016 case FIELD: 2062 case FIELD:
2017 return isolate()->stub_cache()->ComputeKeyedStoreField( 2063 return isolate()->stub_cache()->ComputeKeyedStoreField(
2018 name, receiver, lookup, strict_mode()); 2064 name, receiver, lookup, strict_mode());
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after
2773 #undef ADDR 2819 #undef ADDR
2774 }; 2820 };
2775 2821
2776 2822
2777 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2823 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2778 return IC_utilities[id]; 2824 return IC_utilities[id];
2779 } 2825 }
2780 2826
2781 2827
2782 } } // namespace v8::internal 2828 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698