| 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
|
|
|