| 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);
|
| + }
|
| };
|
|
|
|
|
|
|