Reviewers: Vitaly,

Message:
Vitaly,

may you have a look?

Description:
Do not use possibly stale values for cache size, etc.

Those value can become invalid if cache gets cleared by GC.

Please review this at http://codereview.chromium.org/6348002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/objects-debug.cc
  M src/runtime.cc


Index: src/objects-debug.cc
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 7d50bfb6f6ded8baee3b513d2f242314f4d10be3..f9c57e696078da0a7e2ab6e644f68ddf0f762861 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -670,16 +670,17 @@ void JSFunctionResultCache::JSFunctionResultCacheVerify() {

   int finger = Smi::cast(get(kFingerIndex))->value();
   ASSERT(kEntriesIndex <= finger);
-  ASSERT(finger < size || finger == kEntriesIndex);
+  ASSERT((finger < size) || (finger == kEntriesIndex && finger == size));
   ASSERT_EQ(0, finger % kEntrySize);

   if (FLAG_enable_slow_asserts) {
-    STATIC_ASSERT(2 == kEntrySize);
-    for (int i = kEntriesIndex; i < length(); i += kEntrySize) {
+    for (int i = kEntriesIndex; i < size; i++) {
+      ASSERT(!get(i)->IsTheHole());
+      get(i)->Verify();
+    }
+    for (int i = size; i < length(); i++) {
+      ASSERT(get(i)->IsTheHole());
       get(i)->Verify();
-      get(i + 1)->Verify();
-      // Key and value must be either both the holes, or not.
-      ASSERT(get(i)->IsTheHole() == get(i + 1)->IsTheHole());
     }
   }
 }
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 0cde7779a3d3fbb817b9825129fd5442f0dc2af3..a0497086c73186dd7df9d9e60c8a9b08c24d3e95 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10655,12 +10655,7 @@ static MaybeObject* Runtime_Abort(Arguments args) {


 MUST_USE_RESULT static MaybeObject* CacheMiss(FixedArray* cache_obj,
-                                              int index,
                                               Object* key_obj) {
-  ASSERT(index % 2 == 0);  // index of the key
-  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
-  ASSERT(index < cache_obj->length());
-
   HandleScope scope;

   Handle<FixedArray> cache(cache_obj);
@@ -10683,10 +10678,41 @@ MUST_USE_RESULT static MaybeObject* CacheMiss(FixedArray* cache_obj,
     if (pending_exception) return Failure::Exception();
   }

+#ifdef DEBUG
+ Handle<JSFunctionResultCache>::cast(cache)->JSFunctionResultCacheVerify();
+#endif
+
+  // Function invocation can have cleared the cache.  Reread all the data.
+  const int finger_index =
+      Smi::cast(cache->get(JSFunctionResultCache::kFingerIndex))->value();
+  const int size =
+ Smi::cast(cache->get(JSFunctionResultCache::kCacheSizeIndex))->value();
+
+ // If we have spare room, put new data into it, otherwise evict post finger
+  // entry which is likely to be least recently used.
+  int index = -1;
+  if (size < cache->length()) {
+ cache->set(JSFunctionResultCache::kCacheSizeIndex, Smi::FromInt(size + 2));
+    index = size;
+  } else {
+    index = finger_index + JSFunctionResultCache::kEntrySize;
+    if (index == cache->length()) {
+      index = JSFunctionResultCache::kEntriesIndex;
+    }
+  }
+
+  ASSERT(index % 2 == 0);
+  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
+  ASSERT(index < cache_obj->length());
+
   cache->set(index, *key);
   cache->set(index + 1, *value);
   cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(index));

+#ifdef DEBUG
+ Handle<JSFunctionResultCache>::cast(cache)->JSFunctionResultCacheVerify();
+#endif
+
   return *value;
 }

@@ -10727,18 +10753,7 @@ static MaybeObject* Runtime_GetFromCache(Arguments args) {
     }
   }

-  // Cache miss.  If we have spare room, put new data into it, otherwise
-  // evict post finger entry which must be least recently used.
-  if (size < cache->length()) {
- cache->set(JSFunctionResultCache::kCacheSizeIndex, Smi::FromInt(size + 2));
-    return CacheMiss(cache, size, key);
-  } else {
-    int target_index = finger_index + JSFunctionResultCache::kEntrySize;
-    if (target_index == cache->length()) {
-      target_index = JSFunctionResultCache::kEntriesIndex;
-    }
-    return CacheMiss(cache, target_index, key);
-  }
+  return CacheMiss(cache, key);
 }

 #ifdef DEBUG


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to