Only remove the code object that caused the monomorphic prototype
failure instead of clearing the cache. Clearing the cache makes us miss subsequent monomorphic prototype failures. Review URL: http://codereview.chromium.org/2889 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@318 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
6b4f5aba96
commit
a0257ca1a0
11
src/ic.cc
11
src/ic.cc
@ -143,7 +143,8 @@ IC::State IC::StateFrom(Code* target, Object* receiver) {
|
|||||||
// the receiver map's code cache. Therefore, if the current target
|
// the receiver map's code cache. Therefore, if the current target
|
||||||
// is in the receiver map's code cache, the inline cache failed due
|
// is in the receiver map's code cache, the inline cache failed due
|
||||||
// to prototype check failure.
|
// to prototype check failure.
|
||||||
if (map->IncludedInCodeCache(target)) {
|
int index = map->IndexInCodeCache(target);
|
||||||
|
if (index >= 0) {
|
||||||
// For keyed load/store, the most likely cause of cache failure is
|
// For keyed load/store, the most likely cause of cache failure is
|
||||||
// that the key has changed. We do not distinguish between
|
// that the key has changed. We do not distinguish between
|
||||||
// prototype and non-prototype failures for keyed access.
|
// prototype and non-prototype failures for keyed access.
|
||||||
@ -152,11 +153,9 @@ IC::State IC::StateFrom(Code* target, Object* receiver) {
|
|||||||
return MONOMORPHIC;
|
return MONOMORPHIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the code cache for this map to avoid hitting the same
|
// Remove the target from the code cache to avoid hitting the same
|
||||||
// invalid stub again. It seems likely that most of the code in
|
// invalid stub again.
|
||||||
// the cache is invalid if one of the stubs is so we flush the
|
map->RemoveFromCodeCache(index);
|
||||||
// entire code cache.
|
|
||||||
map->ClearCodeCache();
|
|
||||||
|
|
||||||
return MONOMORPHIC_PROTOTYPE_FAILURE;
|
return MONOMORPHIC_PROTOTYPE_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -2427,13 +2427,21 @@ Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Map::IncludedInCodeCache(Code* code) {
|
int Map::IndexInCodeCache(Code* code) {
|
||||||
FixedArray* array = code_cache();
|
FixedArray* array = code_cache();
|
||||||
int len = array->length();
|
int len = array->length();
|
||||||
for (int i = 0; i < len; i += 2) {
|
for (int i = 0; i < len; i += 2) {
|
||||||
if (array->get(i+1) == code) return true;
|
if (array->get(i + 1) == code) return i + 1;
|
||||||
}
|
}
|
||||||
return false;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Map::RemoveFromCodeCache(int index) {
|
||||||
|
FixedArray* array = code_cache();
|
||||||
|
ASSERT(array->length() >= index && array->get(index)->IsCode());
|
||||||
|
array->set_undefined(index - 1); // key
|
||||||
|
array->set_undefined(index); // code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2343,8 +2343,12 @@ class Map: public HeapObject {
|
|||||||
// Returns the found code or undefined if absent.
|
// Returns the found code or undefined if absent.
|
||||||
Object* FindInCodeCache(String* name, Code::Flags flags);
|
Object* FindInCodeCache(String* name, Code::Flags flags);
|
||||||
|
|
||||||
// Tells whether code is in the code cache.
|
// Returns the non-negative index of the code object if it is in the
|
||||||
bool IncludedInCodeCache(Code* code);
|
// cache and -1 otherwise.
|
||||||
|
int IndexInCodeCache(Code* code);
|
||||||
|
|
||||||
|
// Removes a code object from the code cache at the given index.
|
||||||
|
void RemoveFromCodeCache(int index);
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
void MapIterateBody(ObjectVisitor* v);
|
void MapIterateBody(ObjectVisitor* v);
|
||||||
|
Loading…
Reference in New Issue
Block a user