diff --git a/src/util/hash_table.c b/src/util/hash_table.c index 9ca0d5e2d64..92897c1bc83 100644 --- a/src/util/hash_table.c +++ b/src/util/hash_table.c @@ -234,6 +234,13 @@ _mesa_hash_table_destroy(struct hash_table *ht, ralloc_free(ht); } +static void +hash_table_clear_fast(struct hash_table *ht) +{ + memset(ht->table, 0, sizeof(struct hash_entry) * hash_sizes[ht->size_index].size); + ht->entries = ht->deleted_entries = 0; +} + /** * Deletes all entries of the given hash table without deleting the table * itself or changing its structure. @@ -249,15 +256,17 @@ _mesa_hash_table_clear(struct hash_table *ht, struct hash_entry *entry; - for (entry = ht->table; entry != ht->table + ht->size; entry++) { - if (entry_is_present(ht, entry) && delete_function != NULL) - delete_function(entry); + if (delete_function) { + for (entry = ht->table; entry != ht->table + ht->size; entry++) { + if (entry_is_present(ht, entry)) + delete_function(entry); - entry->key = NULL; - } - - ht->entries = 0; - ht->deleted_entries = 0; + entry->key = NULL; + } + ht->entries = 0; + ht->deleted_entries = 0; + } else + hash_table_clear_fast(ht); } /** Sets the value of the key pointer used for deleted entries in the table. @@ -362,6 +371,12 @@ _mesa_hash_table_rehash(struct hash_table *ht, unsigned new_size_index) struct hash_table old_ht; struct hash_entry *table; + if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) { + hash_table_clear_fast(ht); + assert(!ht->entries); + return; + } + if (new_size_index >= ARRAY_SIZE(hash_sizes)) return; diff --git a/src/util/tests/hash_table/clear.c b/src/util/tests/hash_table/clear.c index e61f60ece1b..90ca30e3a1c 100644 --- a/src/util/tests/hash_table/clear.c +++ b/src/util/tests/hash_table/clear.c @@ -86,6 +86,12 @@ int main() hash_table_foreach(ht, entry) { assert(key_id(entry->key) < SIZE); } + _mesa_hash_table_clear(ht, NULL); + assert(!ht->entries); + assert(!ht->deleted_entries); + hash_table_foreach(ht, entry) { + assert(0); + } _mesa_hash_table_destroy(ht, NULL);