diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 41ad7197b..bc7605e0d 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -789,7 +789,7 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, defer (rw_mutex_unlock(&scope->mutex)); for (auto const &entry : scope->elements) { - String name = entry.key; + String name = scope->elements.keys[entry.hash & (scope->elements.cap-1)]; u32 hash = entry.hash; Entity *decl = entry.value; if (!is_entity_exported(decl, true)) continue; diff --git a/src/checker.hpp b/src/checker.hpp index 9f4ee66d8..226a4ba6a 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -272,15 +272,16 @@ enum { DEFAULT_SCOPE_CAPACITY = 32 }; struct ScopeMapSlot { u32 hash; u32 _pad; - String key; Entity *value; }; enum { SCOPE_MAP_INLINE_CAP = 16 }; struct ScopeMap { - ScopeMapSlot inline_slots[SCOPE_MAP_INLINE_CAP]; + ScopeMapSlot inline_slots[SCOPE_MAP_INLINE_CAP]; + String inline_keys[SCOPE_MAP_INLINE_CAP]; ScopeMapSlot *slots; + String * keys; u32 count; u32 cap; }; @@ -292,11 +293,12 @@ gb_internal gb_inline u32 scope_map_max_load(u32 cap) { gb_internal gb_inline void scope_map_init(ScopeMap *m) { m->cap = SCOPE_MAP_INLINE_CAP; m->slots = m->inline_slots; + m->keys = m->inline_keys; } gb_internal Entity *scope_map_insert_for_rehash( - ScopeMapSlot *slots, u32 mask, + String *keys, ScopeMapSlot *slots, u32 mask, String key, u32 hash, Entity *value) { u32 pos = hash & mask; u32 dist = 0; @@ -305,22 +307,22 @@ gb_internal Entity *scope_map_insert_for_rehash( ScopeMapSlot *s = &slots[pos]; if (s->hash == 0) { - s->key = key; - s->hash = hash; - s->value = value; + keys[pos] = key; + s->hash = hash; + s->value = value; return nullptr; } u32 existing_dist = (pos - s->hash) & mask; if (dist > existing_dist) { - String tmp_key = s->key; + String tmp_key = keys[pos]; u32 tmp_hash = s->hash; Entity *tmp_value = s->value; - s->key = key; - s->hash = hash; - s->value = value; + keys[pos] = key; + s->hash = hash; + s->value = value; hash = tmp_hash; value = tmp_value; @@ -333,23 +335,38 @@ gb_internal Entity *scope_map_insert_for_rehash( } } +gb_internal gb_inline void scope_map_allocate_entries(u32 cap, String **keys, ScopeMapSlot **slots) { + Arena *arena = get_arena(ThreadArena_Permanent); + isize size = (gb_size_of(String) + gb_size_of(ScopeMapSlot)) * cap; + u8 *data = cast(u8 *)arena_alloc(arena, size, 8); + + *keys = cast(String *)data; + *slots = cast(ScopeMapSlot *)(*keys + cap); + + // *keys = permanent_alloc_array(cap); + // *slots = permanent_alloc_array(cap); +} + gb_internal void scope_map_grow(ScopeMap *m) { u32 new_cap = m->cap << 1; u32 new_mask = new_cap - 1; - ScopeMapSlot *new_slots = permanent_alloc_array(new_cap); + String * new_keys; + ScopeMapSlot *new_slots; + scope_map_allocate_entries(new_cap, &new_keys, &new_slots); if (m->count > 0) { for (u32 i = 0; i < m->cap; i++) { if (m->slots[i].hash) { - scope_map_insert_for_rehash(new_slots, new_mask, - m->slots[i].key, m->slots[i].hash, m->slots[i].value); + scope_map_insert_for_rehash(new_keys, new_slots, new_mask, + m->keys[i], m->slots[i].hash, m->slots[i].value); } } } m->slots = new_slots; + m->keys = new_keys; m->cap = new_cap; } @@ -359,7 +376,7 @@ gb_internal void scope_map_reserve(ScopeMap *m, isize capacity) { } u32 new_cap = next_pow2_u32(cast(u32)capacity); if (m->cap < new_cap && new_cap > SCOPE_MAP_INLINE_CAP) { - m->slots = permanent_alloc_array(new_cap); + scope_map_allocate_entries(new_cap, &m->keys, &m->slots); m->cap = new_cap; } } @@ -382,14 +399,14 @@ gb_internal Entity *scope_map_insert(ScopeMap *m, String key, u32 hash, Entity * ScopeMapSlot *s = &m->slots[pos]; if (s->hash == 0) { - s->key = key; + m->keys[pos] = key; s->hash = hash; s->value = value; m->count += 1; return nullptr; } - if (s->hash == hash && s->key == key) { + if (s->hash == hash && m->keys[pos] == key) { Entity *old = s->value; s->value = value; return old; @@ -398,13 +415,13 @@ gb_internal Entity *scope_map_insert(ScopeMap *m, String key, u32 hash, Entity * u32 existing_dist = (pos - s->hash) & mask; if (dist > existing_dist) { - String tmp_key = s->key; + String tmp_key = m->keys[pos]; u32 tmp_hash = s->hash; Entity *tmp_value = s->value; - s->key = key; - s->hash = hash; - s->value = value; + m->keys[pos] = key; + s->hash = hash; + s->value = value; key = tmp_key; hash = tmp_hash; @@ -423,15 +440,16 @@ gb_internal Entity *scope_map_get(ScopeMap *m, String key, u32 hash) { u32 dist = 0; for (;;) { ScopeMapSlot *s = &m->slots[pos]; - if (s->hash == 0) { + u32 curr_hash = s->hash; + if (curr_hash == 0) { return nullptr; } - u32 existing_dist = (pos - s->hash) & mask; + u32 existing_dist = (pos - curr_hash) & mask; if (dist > existing_dist) { return nullptr; } - if (s->hash == hash && s->key == key) { + if (curr_hash == hash && m->keys[pos] == key) { return s->value; } diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 5e9c25016..89b7802ae 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -1050,7 +1050,7 @@ gb_internal OdinDocArray odin_doc_add_pkg_entries(OdinDocWrit defer (array_free(&entries)); for (auto const &element : pkg->scope->elements) { - String name = element.key; + String name = pkg->scope->elements.keys[element.hash & (pkg->scope->elements.cap-1)]; Entity *e = element.value; switch (e->kind) { case Entity_Invalid: diff --git a/src/string.cpp b/src/string.cpp index c26457acf..09bce205e 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -182,8 +182,9 @@ gb_internal isize string_index_byte(String const &s, u8 x) { } gb_internal gb_inline bool str_eq(String const &a, String const &b) { - if (a.len != b.len) return false; - if (a.len == 0) return true; + if (a.len != b.len) return false; + if (a.len == 0) return true; + if (a.text == b.text) return true; return memcmp(a.text, b.text, a.len) == 0; } gb_internal gb_inline bool str_ne(String const &a, String const &b) { return !str_eq(a, b); }