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

Unified Diff: src/ic.cc

Issue 14611006: Cleanup IC heuristics. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic.cc
diff --git a/src/ic.cc b/src/ic.cc
index 080c7bf1b723f87b1449d4d9da58567ddf6ea9fb..024ce18326c888930810ee9827d6bf92a35341ca 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -182,13 +182,12 @@ Address IC::OriginalCodeAddress() const {
static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
Object* receiver,
Object* name) {
- // If the code is NORMAL, it handles dictionary mode objects. Such stubs do
- // not check maps, but do positive/negative lookups.
- if (target->type() != Code::NORMAL) {
- Map* map = target->FindFirstMap();
- if (map != NULL && map->is_deprecated()) {
- return true;
- }
+ if (target->is_keyed_load_stub() ||
danno 2013/05/02 11:36:06 // Determine whether the failure is due to a name
Toon Verwaest 2013/05/02 12:27:20 Done.
+ target->is_keyed_call_stub() ||
+ target->is_keyed_store_stub()) {
+ if (!name->IsName()) return false;
+ Name* stub_name = target->FindFirstName();
+ if (Name::cast(name) != stub_name) return false;
}
InlineCacheHolderFlag cache_holder =
@@ -217,10 +216,22 @@ static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
int index = map->IndexInCodeCache(name, target);
if (index >= 0) {
map->RemoveFromCodeCache(String::cast(name), target, index);
+ if (target->is_load_stub() || target->is_keyed_load_stub()) {
danno 2013/05/02 11:36:06 // For loads, handlers are stored in addition to t
Toon Verwaest 2013/05/02 12:27:20 Done.
+ Code* handler = target->FindFirstCode();
+ index = map->IndexInCodeCache(name, handler);
+ if (index >= 0) {
+ map->RemoveFromCodeCache(String::cast(name), handler, index);
+ }
+ }
return true;
}
- return false;
+ if (cache_holder != OWN_MAP) return false;
danno 2013/05/02 11:36:06 // If the IC is shared between multiple receivers
Toon Verwaest 2013/05/02 12:27:20 Done.
+
+ // Also flag monomorphic prototype failure if the old map was deprecated.
+ Map* old_map = target->FindFirstMap();
+ if (old_map == NULL) return false;
+ return old_map == map || old_map->is_deprecated();
danno 2013/05/02 11:36:06 // The stub is not in the cache. We've ruled out a
Toon Verwaest 2013/05/02 12:27:20 Done.
}
@@ -230,22 +241,13 @@ IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
if (state != MONOMORPHIC || !name->IsString()) return state;
if (receiver->IsUndefined() || receiver->IsNull()) return state;
- // For keyed load/store/call, the most likely cause of cache failure is
- // that the key has changed. We do not distinguish between
- // prototype and non-prototype failures for keyed access.
Code::Kind kind = target->kind();
- if (kind == Code::KEYED_LOAD_IC ||
- kind == Code::KEYED_STORE_IC ||
- kind == Code::KEYED_CALL_IC) {
- return MONOMORPHIC;
- }
-
// Remove the target from the code cache if it became invalid
// because of changes in the prototype chain to avoid hitting it
// again.
// Call stubs handle this later to allow extra IC state
// transitions.
- if (kind != Code::CALL_IC &&
+ if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC &&
TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
return MONOMORPHIC_PROTOTYPE_FAILURE;
}
@@ -724,8 +726,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
object, name);
- } else if (kind_ == Code::CALL_IC &&
- TryRemoveInvalidPrototypeDependentStub(target(),
+ } else if (TryRemoveInvalidPrototypeDependentStub(target(),
*object,
*name)) {
state = MONOMORPHIC_PROTOTYPE_FAILURE;
@@ -748,15 +749,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
case UNINITIALIZED:
case MONOMORPHIC_PROTOTYPE_FAILURE:
case PREMONOMORPHIC:
- set_target(*code);
- break;
case MONOMORPHIC:
- if (code->ic_state() != MONOMORPHIC) {
- Map* map = target()->FindFirstMap();
- if (map != NULL) {
- UpdateMegamorphicCache(map, *name, target());
- }
- }
set_target(*code);
break;
case MEGAMORPHIC: {
@@ -1007,14 +1000,25 @@ bool IC::UpdatePolymorphicIC(State state,
target()->FindAllCode(&handlers, receiver_maps.length());
}
- if (!AddOneReceiverMapIfMissing(&receiver_maps,
- Handle<Map>(receiver->map()))) {
- return false;
+ bool overwrote = false;
danno 2013/05/02 11:36:06 // If the name doesn't match, go generic. Otherwis
Toon Verwaest 2013/05/02 12:27:20 Done.
+ Handle<Map> new_receiver_map(receiver->map());
+ for (int current = 0; current < receiver_maps.length(); ++current) {
+ if (!receiver_maps.at(current).is_null() &&
+ receiver_maps.at(current).is_identical_to(new_receiver_map)) {
+ overwrote = true;
+ handlers.InsertAt(current, code);
+ break;
+ }
+ }
danno 2013/05/02 11:36:06 Move this loop about the code above to get the map
Toon Verwaest 2013/05/02 12:27:20 Done.
+
+ if (!overwrote) {
+ receiver_maps.Add(new_receiver_map);
+ handlers.Add(code);
+ number_of_valid_maps++;
}
- handlers.Add(code);
Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
- &receiver_maps, &handlers, number_of_valid_maps + 1, name);
+ &receiver_maps, &handlers, number_of_valid_maps, name);
set_target(*ic);
return true;
}
@@ -1049,6 +1053,7 @@ void IC::CopyICToMegamorphicCache(Handle<String> name) {
target()->FindAllCode(&handlers, receiver_maps.length());
}
for (int i = 0; i < receiver_maps.length(); i++) {
+ if (receiver_maps.at(i)->is_deprecated()) continue;
danno 2013/05/02 11:36:06 Maybe defer this to Crankshaft? Don't throw away t
Toon Verwaest 2013/05/02 12:27:20 Done.
UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
}
}
@@ -1101,38 +1106,9 @@ void IC::PatchCache(State state,
if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
break;
}
- }
- if (target()->type() != Code::NORMAL) {
- if (target()->is_load_stub()) {
+
+ if (target()->type() != Code::NORMAL) {
CopyICToMegamorphicCache(name);
- } else if (target()->is_store_stub()) {
- // Ensure that the IC stays monomorphic when replacing a monomorphic
- // IC for a deprecated map.
- // TODO(verwaest): Remove this code once polymorphic store ICs are
- // implemented. Updating the polymorphic IC will keep it monomorphic
- // by filtering deprecated maps.
- MapHandleList maps;
- Code* handler = target();
- handler->FindAllMaps(&maps);
- for (int i = 0; i < Min(1, maps.length()); i++) {
- if (maps.at(i)->is_deprecated()) {
- UpdateMonomorphicIC(receiver, code, name);
- return;
- }
- }
- if (maps.length() > 0) {
- if (receiver->map() == *maps.at(0)) {
- UpdateMonomorphicIC(receiver, code, name);
- return;
- }
- UpdateMegamorphicCache(*maps.at(0), *name, handler);
- }
- } else {
- Code* handler = target();
- Map* map = handler->FindFirstMap();
- if (map != NULL) {
- UpdateMegamorphicCache(map, *name, handler);
- }
}
}
@@ -1235,7 +1211,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
}
-void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
+void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
// Cache code holding map should be consistent with
// GenerateMonomorphicCacheProbe.
isolate()->stub_cache()->Set(name, map, code);
@@ -1497,7 +1473,8 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
static bool LookupForWrite(Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value,
- LookupResult* lookup) {
+ LookupResult* lookup,
+ IC::State* state) {
Handle<JSObject> holder = receiver;
receiver->Lookup(*name, lookup);
if (lookup->IsFound()) {
@@ -1534,7 +1511,13 @@ static bool LookupForWrite(Handle<JSObject> receiver,
PropertyDetails target_details =
lookup->GetTransitionDetails(receiver->map());
if (target_details.IsReadOnly()) return false;
- return value->FitsRepresentation(target_details.representation());
+ if (!value->FitsRepresentation(target_details.representation())) {
danno 2013/05/02 11:36:06 Comment this.
Toon Verwaest 2013/05/02 12:27:20 Done.
+ Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map()));
+ Map::GeneralizeRepresentation(
+ target, target->LastAdded(), value->OptimalRepresentation());
+ *state = MONOMORPHIC_PROTOTYPE_FAILURE;
danno 2013/05/02 11:36:06 Check for already deprecated maps? Deprecated maps
Toon Verwaest 2013/05/02 12:27:20 Done.
+ }
+ return true;
}
@@ -1618,7 +1601,7 @@ MaybeObject* StoreIC::Store(State state,
}
LookupResult lookup(isolate());
- if (LookupForWrite(receiver, name, value, &lookup)) {
+ if (LookupForWrite(receiver, name, value, &lookup, &state)) {
if (FLAG_use_ic) {
UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
}
« 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