| Index: runtime/vm/weak_table.cc | 
| =================================================================== | 
| --- runtime/vm/weak_table.cc	(revision 24610) | 
| +++ runtime/vm/weak_table.cc	(working copy) | 
| @@ -9,21 +9,41 @@ | 
|  | 
| namespace dart { | 
|  | 
| -WeakTable* WeakTable::SetValue(RawObject* key, intptr_t val) { | 
| -  intptr_t sz = size(); | 
| -  intptr_t idx = Hash(key) % sz; | 
| +intptr_t WeakTable::SizeFor(intptr_t count, intptr_t size) { | 
| +  intptr_t result = size; | 
| +  if (count <= (size / 4)) { | 
| +    // Reduce the capacity. | 
| +    result = size / 2; | 
| +  } else { | 
| +    // Increase the capacity. | 
| +    result = size * 2; | 
| +    if (result < size) { | 
| +      FATAL("Reached impossible state of having more weak table entries" | 
| +            " than memory available for heap objects."); | 
| +    } | 
| +  } | 
| +  if (result < kMinSize) { | 
| +    result = kMinSize; | 
| +  } | 
| +  return result; | 
| +} | 
| + | 
| + | 
| +void WeakTable::SetValue(RawObject* key, intptr_t val) { | 
| +  intptr_t mask = size() - 1; | 
| +  intptr_t idx = Hash(key) & mask; | 
| intptr_t empty_idx = -1; | 
| RawObject* obj = ObjectAt(idx); | 
|  | 
| while (obj != NULL) { | 
| if (obj == key) { | 
| SetValueAt(idx, val); | 
| -      return this; | 
| +      return; | 
| } else if ((empty_idx < 0) && | 
| (reinterpret_cast<intptr_t>(obj) == kDeletedEntry)) { | 
| empty_idx = idx;  // Insert at this location if not found. | 
| } | 
| -    idx = (idx + 1) % sz; | 
| +    idx = (idx + 1) & mask; | 
| obj = ObjectAt(idx); | 
| } | 
|  | 
| @@ -31,7 +51,7 @@ | 
| // Do not enter an invalid value. Associating 0 with a key deletes it from | 
| // this weak table above in SetValueAt. If the key was not present in the | 
| // weak table we are done. | 
| -    return this; | 
| +    return; | 
| } | 
|  | 
| if (empty_idx >= 0) { | 
| @@ -50,23 +70,46 @@ | 
|  | 
| // Rehash if needed to ensure that there are empty slots available. | 
| if (used_ >= limit()) { | 
| -    return Rehash(); | 
| +    Rehash(); | 
| } | 
| -  return this; | 
| } | 
|  | 
|  | 
| -WeakTable* WeakTable::Rehash() { | 
| -  intptr_t sz = size(); | 
| -  WeakTable* result = NewFrom(this); | 
| +void WeakTable::Rehash() { | 
| +  intptr_t old_size = size(); | 
| +  intptr_t* old_data = data_; | 
|  | 
| -  for (intptr_t i = 0; i < sz; i++) { | 
| +  intptr_t new_size = SizeFor(count(), size()); | 
| +  ASSERT(Utils::IsPowerOfTwo(new_size)); | 
| +  intptr_t* new_data = reinterpret_cast<intptr_t*>( | 
| +      calloc(new_size, kEntrySize * kWordSize)); | 
| + | 
| +  intptr_t mask = new_size - 1; | 
| +  set_used(0); | 
| +  for (intptr_t i = 0; i < old_size; i++) { | 
| if (IsValidEntryAt(i)) { | 
| -      WeakTable* temp = result->SetValue(ObjectAt(i), ValueAt(i)); | 
| -      ASSERT(temp == result); | 
| +      // Find the new hash location for this entry. | 
| +      RawObject* key = ObjectAt(i); | 
| +      intptr_t idx = Hash(key) & mask; | 
| +      RawObject* obj = reinterpret_cast<RawObject*>(new_data[ObjectIndex(idx)]); | 
| +      while (obj != NULL) { | 
| +        ASSERT(obj != key);  // Duplicate entry is not expected. | 
| +        idx = (idx + 1) & mask; | 
| +        obj = reinterpret_cast<RawObject*>(new_data[ObjectIndex(idx)]); | 
| +      } | 
| + | 
| +      new_data[ObjectIndex(idx)] = reinterpret_cast<intptr_t>(key); | 
| +      new_data[ValueIndex(idx)] = ValueAt(i); | 
| +      set_used(used() + 1); | 
| } | 
| } | 
| -  return result; | 
| +  // We should only have used valid entries. | 
| +  ASSERT(used() == count()); | 
| + | 
| +  // Switch to using the newly allocated backing store. | 
| +  size_ = new_size; | 
| +  data_ = new_data; | 
| +  free(old_data); | 
| } | 
|  | 
| }  // namespace dart | 
|  |