Only remove the code object that caused the monomorphic prototype
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Sep 2008 12:41:36 +0000 (12:41 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Sep 2008 12:41:36 +0000 (12:41 +0000)
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

src/ic.cc
src/objects.cc
src/objects.h

index be90d8034482050f8ecc7a05ed50a5080e6b5714..59794ea723a060e9ebc7e298cdf4276c8445833e 100644 (file)
--- a/src/ic.cc
+++ b/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
   // is in the receiver map's code cache, the inline cache failed due
   // 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
     // that the key has changed.  We do not distinguish between
     // prototype and non-prototype failures for keyed access.
@@ -152,11 +153,9 @@ IC::State IC::StateFrom(Code* target, Object* receiver) {
       return MONOMORPHIC;
     }
 
-    // Clear the code cache for this map to avoid hitting the same
-    // invalid stub again.  It seems likely that most of the code in
-    // the cache is invalid if one of the stubs is so we flush the
-    // entire code cache.
-    map->ClearCodeCache();
+    // Remove the target from the code cache to avoid hitting the same
+    // invalid stub again.
+    map->RemoveFromCodeCache(index);
 
     return MONOMORPHIC_PROTOTYPE_FAILURE;
   }
index 22640e8a5750db238cae4044527aa1a288cc5520..1e42d0244c9bd7bdfe6559dc41d1b33470b20293 100644 (file)
@@ -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();
   int len = array->length();
   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
 }
 
 
index 841db2d0e4aa3b0283da53da1761db0347528e2a..53a2fece8adadfb1a0b05e5c1d1b907de1ef6608 100644 (file)
@@ -2343,8 +2343,12 @@ class Map: public HeapObject {
   // Returns the found code or undefined if absent.
   Object* FindInCodeCache(String* name, Code::Flags flags);
 
-  // Tells whether code is in the code cache.
-  bool IncludedInCodeCache(Code* code);
+  // Returns the non-negative index of the code object if it is in the
+  // 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.
   void MapIterateBody(ObjectVisitor* v);