| Index: src/heap.cc
 | 
| ===================================================================
 | 
| --- src/heap.cc	(revision 10510)
 | 
| +++ src/heap.cc	(working copy)
 | 
| @@ -902,8 +902,7 @@
 | 
|  
 | 
|    CompletelyClearInstanceofCache();
 | 
|  
 | 
| -  // TODO(1605) select heuristic for flushing NumberString cache with
 | 
| -  // FlushNumberStringCache
 | 
| +  FlushNumberStringCache();
 | 
|    if (FLAG_cleanup_code_caches_at_gc) {
 | 
|      polymorphic_code_cache()->set_cache(undefined_value());
 | 
|    }
 | 
| @@ -2512,7 +2511,10 @@
 | 
|    }
 | 
|    set_intrinsic_function_names(StringDictionary::cast(obj));
 | 
|  
 | 
| -  if (InitializeNumberStringCache()->IsFailure()) return false;
 | 
| +  { MaybeObject* maybe_obj = AllocateInitialNumberStringCache();
 | 
| +    if (!maybe_obj->ToObject(&obj)) return false;
 | 
| +  }
 | 
| +  set_number_string_cache(FixedArray::cast(obj));
 | 
|  
 | 
|    // Allocate cache for single character ASCII strings.
 | 
|    { MaybeObject* maybe_obj =
 | 
| @@ -2622,20 +2624,44 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| -MaybeObject* Heap::InitializeNumberStringCache() {
 | 
| -  // Compute the size of the number string cache based on the max heap size.
 | 
| -  // max_semispace_size_ == 512 KB => number_string_cache_size = 32.
 | 
| -  // max_semispace_size_ ==   8 MB => number_string_cache_size = 16KB.
 | 
| -  int number_string_cache_size = max_semispace_size_ / 512;
 | 
| -  number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size));
 | 
| -  Object* obj;
 | 
| +MaybeObject* Heap::AllocateInitialNumberStringCache() {
 | 
|    MaybeObject* maybe_obj =
 | 
| -      AllocateFixedArray(number_string_cache_size * 2, TENURED);
 | 
| -  if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj));
 | 
| +      AllocateFixedArray(kInitialNumberStringCacheSize * 2, TENURED);
 | 
|    return maybe_obj;
 | 
|  }
 | 
|  
 | 
|  
 | 
| +int Heap::FullSizeNumberStringCacheLength() {
 | 
| +  // Compute the size of the number string cache based on the max newspace size.
 | 
| +  // The number string cache has a minimum size based on twice the initial cache
 | 
| +  // size to ensure that it is bigger after being made 'full size'.
 | 
| +  int number_string_cache_size = max_semispace_size_ / 512;
 | 
| +  number_string_cache_size = Max(kInitialNumberStringCacheSize * 2,
 | 
| +                                 Min(0x4000, number_string_cache_size));
 | 
| +  // There is a string and a number per entry so the length is twice the number
 | 
| +  // of entries.
 | 
| +  return number_string_cache_size * 2;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Heap::AllocateFullSizeNumberStringCache() {
 | 
| +  // The idea is to have a small number string cache in the snapshot to keep
 | 
| +  // boot-time memory usage down.  If we expand the number string cache already
 | 
| +  // while creating the snapshot then that didn't work out.
 | 
| +  ASSERT(!Serializer::enabled());
 | 
| +  MaybeObject* maybe_obj =
 | 
| +      AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED);
 | 
| +  Object* new_cache;
 | 
| +  if (maybe_obj->ToObject(&new_cache)) {
 | 
| +    // We don't bother to repopulate the cache with entries from the old cache.
 | 
| +    // It will be repopulated soon enough with new strings.
 | 
| +    set_number_string_cache(FixedArray::cast(new_cache));
 | 
| +  }
 | 
| +  // If allocation fails then we just return without doing anything.  It is only
 | 
| +  // a cache, so best effort is OK here.
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Heap::FlushNumberStringCache() {
 | 
|    // Flush the number to string cache.
 | 
|    int len = number_string_cache()->length();
 | 
| @@ -2681,11 +2707,17 @@
 | 
|    int mask = (number_string_cache()->length() >> 1) - 1;
 | 
|    if (number->IsSmi()) {
 | 
|      hash = smi_get_hash(Smi::cast(number)) & mask;
 | 
| -    number_string_cache()->set(hash * 2, Smi::cast(number));
 | 
|    } else {
 | 
|      hash = double_get_hash(number->Number()) & mask;
 | 
| -    number_string_cache()->set(hash * 2, number);
 | 
|    }
 | 
| +  if (number_string_cache()->get(hash * 2) != undefined_value() &&
 | 
| +      number_string_cache()->length() != FullSizeNumberStringCacheLength()) {
 | 
| +    // The first time we have a hash collision, we move to the full sized
 | 
| +    // number string cache.
 | 
| +    AllocateFullSizeNumberStringCache();
 | 
| +    return;
 | 
| +  }
 | 
| +  number_string_cache()->set(hash * 2, number);
 | 
|    number_string_cache()->set(hash * 2 + 1, string);
 | 
|  }
 | 
|  
 | 
| 
 |