Index: runtime/vm/hash_table.h |
=================================================================== |
--- runtime/vm/hash_table.h (revision 38342) |
+++ runtime/vm/hash_table.h (working copy) |
@@ -78,6 +78,7 @@ |
template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> |
class HashTable : public ValueObject { |
public: |
+ typedef KeyTraits Traits; |
explicit HashTable(Array& data) : data_(data) {} |
RawArray* Release() { |
@@ -383,9 +384,10 @@ |
public: |
// Allocates and initializes a table. |
template<typename Table> |
- static RawArray* New(intptr_t initial_capacity) { |
+ static RawArray* New(intptr_t initial_capacity, |
+ Heap::Space space = Heap::kNew) { |
Table table(Array::Handle(Array::New( |
- Table::ArrayLengthForNumOccupied(initial_capacity)))); |
+ Table::ArrayLengthForNumOccupied(initial_capacity), space))); |
table.Initialize(); |
return table.Release(); |
} |
@@ -423,7 +425,9 @@ |
} |
double target = (low + high) / 2.0; |
intptr_t new_capacity = (1 + table.NumOccupied()) / target; |
- Table new_table(Array::Handle(New<Table>(new_capacity))); |
+ Table new_table(Array::Handle(New<Table>( |
+ new_capacity, |
+ table.data_.IsOld() ? Heap::kOld : Heap::kNew))); |
Copy(table, new_table); |
table.data_ = new_table.Release(); |
} |
@@ -465,7 +469,7 @@ |
return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); |
} |
bool UpdateOrInsert(const Object& key, const Object& value) const { |
- HashTables::EnsureLoadFactor(0.0, 0.75, *this); |
+ EnsureCapacity(); |
intptr_t entry = -1; |
bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); |
if (!present) { |
@@ -481,6 +485,36 @@ |
ASSERT(entry != -1); |
BaseIterTable::UpdatePayload(entry, 0, value); |
} |
+ // If 'key' is not present, maps it to 'value_if_absent'. Returns the final |
+ // value in the map. |
+ RawObject* InsertOrGetValue(const Object& key, |
+ const Object& value_if_absent) const { |
+ EnsureCapacity(); |
+ intptr_t entry = -1; |
+ if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { |
+ BaseIterTable::InsertKey(entry, key); |
+ BaseIterTable::UpdatePayload(entry, 0, value_if_absent); |
+ return value_if_absent.raw(); |
+ } else { |
+ return BaseIterTable::GetPayload(entry, 0); |
+ } |
+ } |
+ // Like InsertOrGetValue, but calls NewKey to allocate a key object if needed. |
+ template<typename Key> |
+ RawObject* InsertNewOrGetValue(const Key& key, |
+ const Object& value_if_absent) const { |
+ EnsureCapacity(); |
+ intptr_t entry = -1; |
+ if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { |
+ Object& new_key = Object::Handle( |
+ BaseIterTable::BaseTable::Traits::NewKey(key)); |
+ BaseIterTable::InsertKey(entry, new_key); |
+ BaseIterTable::UpdatePayload(entry, 0, value_if_absent); |
+ return value_if_absent.raw(); |
+ } else { |
+ return BaseIterTable::GetPayload(entry, 0); |
+ } |
+ } |
template<typename Key> |
bool Remove(const Key& key) const { |
@@ -492,6 +526,12 @@ |
return true; |
} |
} |
+ |
+ protected: |
+ void EnsureCapacity() const { |
+ static const double kMaxLoadFactor = 0.75; |
+ HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
+ } |
}; |
@@ -516,7 +556,7 @@ |
public: |
explicit HashSet(Array& data) : BaseIterTable(data) {} |
bool Insert(const Object& key) { |
- HashTables::EnsureLoadFactor(0.0, 0.75, *this); |
+ EnsureCapacity(); |
intptr_t entry = -1; |
bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); |
if (!present) { |
@@ -524,7 +564,45 @@ |
} |
return present; |
} |
+ |
+ // If 'key' is not present, insert and return it. Else, return the existing |
+ // key in the set (useful for canonicalization). |
+ RawObject* InsertOrGet(const Object& key) const { |
+ EnsureCapacity(); |
+ intptr_t entry = -1; |
+ if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { |
+ BaseIterTable::InsertKey(entry, key); |
+ return key.raw(); |
+ } else { |
+ return BaseIterTable::GetPayload(entry, 0); |
+ } |
+ } |
+ |
+ // Like InsertOrGet, but calls NewKey to allocate a key object if needed. |
template<typename Key> |
+ RawObject* InsertNewOrGet(const Key& key) const { |
+ EnsureCapacity(); |
+ intptr_t entry = -1; |
+ if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { |
+ Object& new_key = Object::Handle( |
+ BaseIterTable::BaseTable::Traits::NewKey(key)); |
+ BaseIterTable::InsertKey(entry, new_key); |
+ return new_key.raw(); |
+ } else { |
+ return BaseIterTable::GetKey(entry); |
+ } |
+ } |
+ |
+ template<typename Key> |
+ RawObject* GetOrNull(const Key& key, bool* present = NULL) const { |
+ intptr_t entry = BaseIterTable::FindKey(key); |
+ if (present != NULL) { |
+ *present = (entry != -1); |
+ } |
+ return (entry == -1) ? Object::null() : BaseIterTable::GetKey(entry); |
+ } |
+ |
+ template<typename Key> |
bool Remove(const Key& key) const { |
intptr_t entry = BaseIterTable::FindKey(key); |
if (entry == -1) { |
@@ -534,6 +612,12 @@ |
return true; |
} |
} |
+ |
+ protected: |
+ void EnsureCapacity() const { |
+ static const double kMaxLoadFactor = 0.75; |
+ HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
+ } |
}; |