Index: runtime/vm/weak_table.h |
=================================================================== |
--- runtime/vm/weak_table.h (revision 24610) |
+++ runtime/vm/weak_table.h (working copy) |
@@ -14,32 +14,34 @@ |
class WeakTable { |
public: |
+ WeakTable() : size_(kMinSize), used_(0), count_(0) { |
+ ASSERT(Utils::IsPowerOfTwo(size_)); |
+ data_ = reinterpret_cast<intptr_t*>(calloc(size_, kEntrySize * kWordSize)); |
+ } |
explicit WeakTable(intptr_t size) : used_(0), count_(0) { |
ASSERT(size >= 0); |
+ ASSERT(Utils::IsPowerOfTwo(kMinSize)); |
if (size < kMinSize) { |
size = kMinSize; |
} |
- data_ = reinterpret_cast<intptr_t*>(calloc(size, kEntrySize * kWordSize)); |
+ // Get a max size that avoids overflows. |
+ const intptr_t kMaxSize = |
+ (kIntptrOne << (kBitsPerWord - 2)) / (kEntrySize * kWordSize); |
+ ASSERT(Utils::IsPowerOfTwo(kMaxSize)); |
+ if (size > kMaxSize) { |
+ size = kMaxSize; |
+ } |
size_ = size; |
+ ASSERT(Utils::IsPowerOfTwo(size_)); |
+ data_ = reinterpret_cast<intptr_t*>(calloc(size_, kEntrySize * kWordSize)); |
} |
+ ~WeakTable() { |
+ free(data_); |
+ } |
+ |
static WeakTable* NewFrom(WeakTable* original) { |
- intptr_t cnt = original->count(); |
- intptr_t sz = original->size(); |
- intptr_t new_sz = sz; |
- |
- if (cnt <= (sz / 4)) { |
- // Reduce the capacity. |
- new_sz = sz / 2; |
- } else if (cnt > (sz / 2)) { |
- // Increase the capacity. |
- new_sz = sz * 2; |
- if (new_sz < sz) { |
- FATAL("Reached impossible state of having more weak table entries" |
- " than memory available for heap objects."); |
- } |
- } |
- return new WeakTable(new_sz); |
+ return new WeakTable(SizeFor(original->count(), original->size())); |
} |
intptr_t size() const { return size_; } |
@@ -62,24 +64,28 @@ |
} |
RawObject* ObjectAt(intptr_t i) const { |
+ ASSERT(i >= 0); |
+ ASSERT(i < size()); |
return reinterpret_cast<RawObject*>(data_[ObjectIndex(i)]); |
} |
intptr_t ValueAt(intptr_t i) const { |
+ ASSERT(i >= 0); |
+ ASSERT(i < size()); |
return data_[ValueIndex(i)]; |
} |
- WeakTable* SetValue(RawObject* key, intptr_t val); |
+ void SetValue(RawObject* key, intptr_t val); |
intptr_t GetValue(RawObject* key) const { |
- intptr_t sz = size(); |
- intptr_t idx = Hash(key) % sz; |
+ intptr_t mask = size() - 1; |
+ intptr_t idx = Hash(key) & mask; |
RawObject* obj = ObjectAt(idx); |
while (obj != NULL) { |
if (obj == key) { |
return ValueAt(idx); |
} |
- idx = (idx + 1) % sz; |
+ idx = (idx + 1) & mask; |
obj = ObjectAt(idx); |
} |
ASSERT(ValueAt(idx) == 0); |
@@ -96,6 +102,7 @@ |
static const intptr_t kDeletedEntry = 1; // Equivalent to a tagged NULL. |
static const intptr_t kMinSize = 8; |
+ static intptr_t SizeFor(intptr_t count, intptr_t size); |
static intptr_t LimitFor(intptr_t size) { |
// Maintain a maximum of 75% fill rate. |
return 3 * (size / 4); |
@@ -103,8 +110,6 @@ |
intptr_t limit() const { return LimitFor(size()); } |
intptr_t index(intptr_t i) const { |
- ASSERT(i >= 0); |
- ASSERT(i < size()); |
return i * kEntrySize; |
} |
@@ -128,10 +133,14 @@ |
} |
void SetObjectAt(intptr_t i, RawObject* key) { |
+ ASSERT(i >= 0); |
+ ASSERT(i < size()); |
data_[ObjectIndex(i)] = reinterpret_cast<intptr_t>(key); |
} |
void SetValueAt(intptr_t i, intptr_t val) { |
+ ASSERT(i >= 0); |
+ ASSERT(i < size()); |
// Setting a value of 0 is equivalent to invalidating the entry. |
if (val == 0) { |
data_[ObjectIndex(i)] = kDeletedEntry; |
@@ -140,7 +149,7 @@ |
data_[ValueIndex(i)] = val; |
} |
- WeakTable* Rehash(); |
+ void Rehash(); |
static intptr_t Hash(RawObject* key) { |
return reinterpret_cast<intptr_t>(key) >> kObjectAlignmentLog2; |
@@ -155,7 +164,7 @@ |
intptr_t used_; |
intptr_t count_; |
- DISALLOW_IMPLICIT_CONSTRUCTORS(WeakTable); |
+ DISALLOW_COPY_AND_ASSIGN(WeakTable); |
}; |
} // namespace dart |