| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 0cde7779a3d3fbb817b9825129fd5442f0dc2af3..2f1f54c6965cab37030644e5d29e3794a7c9c0cd 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -10654,51 +10654,12 @@ 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);
|
| - Handle<Object> key(key_obj);
|
| - Handle<JSFunction> factory(JSFunction::cast(
|
| - cache->get(JSFunctionResultCache::kFactoryIndex)));
|
| - // TODO(antonm): consider passing a receiver when constructing a cache.
|
| - Handle<Object> receiver(Top::global_context()->global());
|
| -
|
| - Handle<Object> value;
|
| - {
|
| - // This handle is nor shared, nor used later, so it's safe.
|
| - Object** argv[] = { key.location() };
|
| - bool pending_exception = false;
|
| - value = Execution::Call(factory,
|
| - receiver,
|
| - 1,
|
| - argv,
|
| - &pending_exception);
|
| - if (pending_exception) return Failure::Exception();
|
| - }
|
| -
|
| - cache->set(index, *key);
|
| - cache->set(index + 1, *value);
|
| - cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(index));
|
| -
|
| - return *value;
|
| -}
|
| -
|
| -
|
| static MaybeObject* Runtime_GetFromCache(Arguments args) {
|
| // This is only called from codegen, so checks might be more lax.
|
| - CONVERT_CHECKED(FixedArray, cache, args[0]);
|
| + CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]);
|
| Object* key = args[1];
|
|
|
| - const int finger_index =
|
| - Smi::cast(cache->get(JSFunctionResultCache::kFingerIndex))->value();
|
| -
|
| + int finger_index = cache->finger_index();
|
| Object* o = cache->get(finger_index);
|
| if (o == key) {
|
| // The fastest case: hit the same place again.
|
| @@ -10710,35 +10671,78 @@ static MaybeObject* Runtime_GetFromCache(Arguments args) {
|
| i -= 2) {
|
| o = cache->get(i);
|
| if (o == key) {
|
| - cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i));
|
| + cache->set_finger_index(i);
|
| return cache->get(i + 1);
|
| }
|
| }
|
|
|
| - const int size =
|
| - Smi::cast(cache->get(JSFunctionResultCache::kCacheSizeIndex))->value();
|
| + int size = cache->size();
|
| ASSERT(size <= cache->length());
|
|
|
| for (int i = size - 2; i > finger_index; i -= 2) {
|
| o = cache->get(i);
|
| if (o == key) {
|
| - cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i));
|
| + cache->set_finger_index(i);
|
| return cache->get(i + 1);
|
| }
|
| }
|
|
|
| - // 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);
|
| + // There is no value in the cache. Invoke the function and cache result.
|
| + HandleScope scope;
|
| +
|
| + Handle<JSFunctionResultCache> cache_handle(cache);
|
| + Handle<Object> key_handle(key);
|
| + Handle<Object> value;
|
| + {
|
| + Handle<JSFunction> factory(JSFunction::cast(
|
| + cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
|
| + // TODO(antonm): consider passing a receiver when constructing a cache.
|
| + Handle<Object> receiver(Top::global_context()->global());
|
| + // This handle is nor shared, nor used later, so it's safe.
|
| + Object** argv[] = { key_handle.location() };
|
| + bool pending_exception = false;
|
| + value = Execution::Call(factory,
|
| + receiver,
|
| + 1,
|
| + argv,
|
| + &pending_exception);
|
| + if (pending_exception) return Failure::Exception();
|
| + }
|
| +
|
| +#ifdef DEBUG
|
| + cache_handle->JSFunctionResultCacheVerify();
|
| +#endif
|
| +
|
| + // Function invocation may have cleared the cache. Reread all the data.
|
| + finger_index = cache_handle->finger_index();
|
| + size = cache_handle->size();
|
| +
|
| + // If we have spare room, put new data into it, otherwise evict post finger
|
| + // entry which is likely to be the least recently used.
|
| + int index = -1;
|
| + if (size < cache_handle->length()) {
|
| + cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
|
| + index = size;
|
| } else {
|
| - int target_index = finger_index + JSFunctionResultCache::kEntrySize;
|
| - if (target_index == cache->length()) {
|
| - target_index = JSFunctionResultCache::kEntriesIndex;
|
| + index = finger_index + JSFunctionResultCache::kEntrySize;
|
| + if (index == cache_handle->length()) {
|
| + index = JSFunctionResultCache::kEntriesIndex;
|
| }
|
| - return CacheMiss(cache, target_index, key);
|
| }
|
| +
|
| + ASSERT(index % 2 == 0);
|
| + ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
|
| + ASSERT(index < cache_handle->length());
|
| +
|
| + cache_handle->set(index, *key_handle);
|
| + cache_handle->set(index + 1, *value);
|
| + cache_handle->set_finger_index(index);
|
| +
|
| +#ifdef DEBUG
|
| + cache_handle->JSFunctionResultCacheVerify();
|
| +#endif
|
| +
|
| + return *value;
|
| }
|
|
|
| #ifdef DEBUG
|
|
|