diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 09ad3508c..04c754649 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -349,7 +349,7 @@ void override_entity_in_scope(Entity *original_entity, Entity *new_entity) { // GB_ASSERT_MSG(found_entity == original_entity, "%.*s == %.*s", LIT(found_entity->token.string), LIT(new_entity->token.string)); - map_set(&found_scope->elements, hash_string(original_name), new_entity); + string_map_set(&found_scope->elements, original_name, new_entity); } @@ -777,8 +777,8 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { init_entity_foreign_library(ctx, e); auto *fp = &ctx->info->foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); + StringHashKey key = string_hash_string(name); + Entity **found = string_map_get(fp, key); if (found) { Entity *f = *found; TokenPos pos = f->token.pos; @@ -800,7 +800,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } else if (name == "main") { error(d->proc_lit, "The link name 'main' is reserved for internal use"); } else { - map_set(fp, key, e); + string_map_set(fp, key, e); } } else { String name = e->token.string; @@ -809,8 +809,8 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } if (e->Procedure.link_name.len > 0 || is_export) { auto *fp = &ctx->info->foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); + StringHashKey key = string_hash_string(name); + Entity **found = string_map_get(fp, key); if (found) { Entity *f = *found; TokenPos pos = f->token.pos; @@ -822,7 +822,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } else if (name == "main") { error(d->proc_lit, "The link name 'main' is reserved for internal use"); } else { - map_set(fp, key, e); + string_map_set(fp, key, e); } } } @@ -898,8 +898,8 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, } auto *fp = &ctx->info->foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); + StringHashKey key = string_hash_string(name); + Entity **found = string_map_get(fp, key); if (found) { Entity *f = *found; TokenPos pos = f->token.pos; @@ -912,7 +912,7 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, LIT(name), LIT(pos.file), pos.line, pos.column); } } else { - map_set(fp, key, e); + string_map_set(fp, key, e); } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 12712443f..e446752a1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1065,8 +1065,6 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ } } - HashKey key = hash_string(e->token.string); - if (e->kind == Entity_ProcGroup) { auto *pge = &e->ProcGroup; @@ -6421,9 +6419,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type // NOTE(bill): This is give type hints for the named parameters // in order to improve the type inference system - Map type_hint_map = {}; // Key: String - map_init(&type_hint_map, heap_allocator(), 2*ce->args.count); - defer (map_destroy(&type_hint_map)); + StringMap type_hint_map = {}; // Key: String + string_map_init(&type_hint_map, heap_allocator(), 2*ce->args.count); + defer (string_map_destroy(&type_hint_map)); Type *ptype = nullptr; bool single_case = true; @@ -6453,7 +6451,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type if (is_blank_ident(e->token)) { continue; } - map_set(&type_hint_map, hash_string(e->token.string), e->type); + string_map_set(&type_hint_map, e->token.string, e->type); } } } @@ -6475,8 +6473,8 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type if (is_blank_ident(e->token)) { continue; } - HashKey key = hash_string(e->token.string); - Type **found = map_get(&type_hint_map, key); + StringHashKey key = string_hash_string(e->token.string); + Type **found = string_map_get(&type_hint_map, key); if (found) { Type *t = *found; if (t == nullptr) { @@ -6487,10 +6485,10 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type // NOTE(bill): No need to set again } else { // NOTE(bill): Ambiguous named parameter across all types so set it to a nullptr - map_set(&type_hint_map, key, cast(Type *)nullptr); + string_map_set(&type_hint_map, key, cast(Type *)nullptr); } } else { - map_set(&type_hint_map, key, e->type); + string_map_set(&type_hint_map, key, e->type); } } } @@ -6508,7 +6506,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type if (field != nullptr && field->kind == Ast_Ident) { String key = field->Ident.token.string; - Type **found = map_get(&type_hint_map, hash_string(key)); + Type **found = string_map_get(&type_hint_map, key); if (found) { type_hint = *found; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index be2f6b06a..0c90e08f0 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1959,8 +1959,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { init_entity_foreign_library(ctx, e); auto *fp = &ctx->checker->info.foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); + StringHashKey key = string_hash_string(name); + Entity **found = string_map_get(fp, key); if (found) { Entity *f = *found; TokenPos pos = f->token.pos; @@ -1973,7 +1973,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { LIT(name), LIT(pos.file), pos.line, pos.column); } } else { - map_set(fp, key, e); + string_map_set(fp, key, e); } } else if (e->flags & EntityFlag_Static) { if (vd->values.count > 0) { diff --git a/src/checker.cpp b/src/checker.cpp index d58cb1fde..517a63506 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -29,14 +29,14 @@ void scope_reset(Scope *scope) { scope->first_child = nullptr; scope->last_child = nullptr; - map_clear (&scope->elements); + string_map_clear(&scope->elements); ptr_set_clear(&scope->imported); } void scope_reserve(Scope *scope, isize capacity) { isize cap = 2*capacity; if (cap > scope->elements.hashes.count) { - map_rehash(&scope->elements, capacity); + string_map_rehash(&scope->elements, capacity); } } @@ -221,7 +221,7 @@ bool decl_info_has_init(DeclInfo *d) { Scope *create_scope(Scope *parent, gbAllocator allocator, isize init_elements_capacity=16) { Scope *s = gb_alloc_item(allocator, Scope); s->parent = parent; - map_init(&s->elements, heap_allocator(), init_elements_capacity); + string_map_init(&s->elements, heap_allocator(), init_elements_capacity); ptr_set_init(&s->imported, heap_allocator(), 0); s->delayed_imports.allocator = heap_allocator(); @@ -295,7 +295,7 @@ void destroy_scope(Scope *scope) { destroy_scope(child); } - map_destroy(&scope->elements); + string_map_destroy(&scope->elements); array_free(&scope->delayed_imports); array_free(&scope->delayed_directives); ptr_set_destroy(&scope->imported); @@ -340,21 +340,20 @@ void check_close_scope(CheckerContext *c) { } -Entity *scope_lookup_current(Scope *s, String name) { - HashKey key = hash_string(name); - Entity **found = map_get(&s->elements, key); +Entity *scope_lookup_current(Scope *s, String const &name) { + Entity **found = string_map_get(&s->elements, name); if (found) { return *found; } return nullptr; } -void scope_lookup_parent(Scope *scope, String name, Scope **scope_, Entity **entity_) { +void scope_lookup_parent(Scope *scope, String const &name, Scope **scope_, Entity **entity_) { bool gone_thru_proc = false; bool gone_thru_package = false; - HashKey key = hash_string(name); + StringHashKey key = string_hash_string(name); for (Scope *s = scope; s != nullptr; s = s->parent) { - Entity **found = map_get(&s->elements, key); + Entity **found = string_map_get(&s->elements, key); if (found) { Entity *e = *found; if (gone_thru_proc) { @@ -386,7 +385,7 @@ void scope_lookup_parent(Scope *scope, String name, Scope **scope_, Entity **ent if (scope_) *scope_ = nullptr; } -Entity *scope_lookup(Scope *s, String name) { +Entity *scope_lookup(Scope *s, String const &name) { Entity *entity = nullptr; scope_lookup_parent(s, name, nullptr, &entity); return entity; @@ -394,18 +393,18 @@ Entity *scope_lookup(Scope *s, String name) { -Entity *scope_insert_with_name(Scope *s, String name, Entity *entity) { +Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity) { if (name == "") { return nullptr; } - HashKey key = hash_string(name); - Entity **found = map_get(&s->elements, key); + StringHashKey key = string_hash_string(name); + Entity **found = string_map_get(&s->elements, key); if (found) { return *found; } if (s->parent != nullptr && (s->parent->flags & ScopeFlag_Proc) != 0) { - Entity **found = map_get(&s->parent->elements, key); + Entity **found = string_map_get(&s->parent->elements, key); if (found) { if ((*found)->flags & EntityFlag_Result) { return *found; @@ -413,7 +412,7 @@ Entity *scope_insert_with_name(Scope *s, String name, Entity *entity) { } } - map_set(&s->elements, key, entity); + string_map_set(&s->elements, key, entity); if (entity->scope == nullptr) { entity->scope = s; } @@ -611,8 +610,7 @@ AstPackage *get_core_package(CheckerInfo *info, String name) { gbAllocator a = heap_allocator(); String path = get_fullpath_core(a, name); defer (gb_free(a, path.text)); - HashKey key = hash_string(path); - auto found = map_get(&info->packages, key); + auto found = string_map_get(&info->packages, path); GB_ASSERT_MSG(found != nullptr, "Missing core package %.*s", LIT(name)); return *found; } @@ -744,7 +742,7 @@ void init_universal(void) { bool defined_values_double_declaration = false; for_array(i, bc->defined_values.entries) { - String name = bc->defined_values.entries[i].key.string; + char const *name = cast(char const *)cast(uintptr)bc->defined_values.entries[i].key.key; ExactValue value = bc->defined_values.entries[i].value; GB_ASSERT(value.kind != ExactValue_Invalid); @@ -770,7 +768,7 @@ void init_universal(void) { Entity *entity = alloc_entity_constant(nullptr, make_token_ident(name), type, value); entity->state = EntityState_Resolved; if (scope_insert(builtin_pkg->scope, entity)) { - error(entity->token, "'%.*s' defined as an argument is already declared at the global scope", LIT(name)); + error(entity->token, "'%s' defined as an argument is already declared at the global scope", name); defined_values_double_declaration = true; // NOTE(bill): Just exit early before anything, even though the compiler will do that anyway } @@ -797,13 +795,13 @@ void init_checker_info(CheckerInfo *i) { array_init(&i->definitions, a); array_init(&i->entities, a); map_init(&i->untyped, a); - map_init(&i->foreigns, a); + string_map_init(&i->foreigns, a); map_init(&i->gen_procs, a); map_init(&i->gen_types, a); array_init(&i->type_info_types, a); map_init(&i->type_info_map, a); - map_init(&i->files, a); - map_init(&i->packages, a); + string_map_init(&i->files, a); + string_map_init(&i->packages, a); array_init(&i->variable_init_order, a); array_init(&i->required_foreign_imports_through_force, a); array_init(&i->required_global_variables, a); @@ -818,13 +816,13 @@ void destroy_checker_info(CheckerInfo *i) { array_free(&i->definitions); array_free(&i->entities); map_destroy(&i->untyped); - map_destroy(&i->foreigns); + string_map_destroy(&i->foreigns); map_destroy(&i->gen_procs); map_destroy(&i->gen_types); array_free(&i->type_info_types); map_destroy(&i->type_info_map); - map_destroy(&i->files); - map_destroy(&i->packages); + string_map_destroy(&i->files); + string_map_destroy(&i->packages); array_free(&i->variable_init_order); array_free(&i->identifier_uses); array_free(&i->required_foreign_imports_through_force); @@ -956,7 +954,7 @@ DeclInfo *decl_info_of_ident(Ast *ident) { } AstFile *ast_file_of_filename(CheckerInfo *i, String filename) { - AstFile **found = map_get(&i->files, hash_string(filename)); + AstFile **found = string_map_get(&i->files, filename); if (found != nullptr) { return *found; } @@ -994,7 +992,7 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { // TODO(bill): This is O(n) and can be very slow for_array(i, info->type_info_map.entries){ auto *e = &info->type_info_map.entries[i]; - Type *prev_type = cast(Type *)e->key.ptr; + Type *prev_type = cast(Type *)cast(uintptr)e->key.key; if (are_types_identical(prev_type, type)) { entry_index = e->value; // NOTE(bill): Add it to the search map @@ -1234,7 +1232,7 @@ void add_type_info_type(CheckerContext *c, Type *t) { isize ti_index = -1; for_array(i, c->info->type_info_map.entries) { auto *e = &c->info->type_info_map.entries[i]; - Type *prev_type = cast(Type *)e->key.ptr; + Type *prev_type = cast(Type *)cast(uintptr)e->key.key; if (are_types_identical(t, prev_type)) { // Duplicate entry ti_index = e->value; @@ -1811,7 +1809,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info) { TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 1"); // Calculate edges for graph M for_array(i, M.entries) { - Entity * e = cast(Entity *)M.entries[i].key.ptr; + Entity * e = cast(Entity *)cast(uintptr)M.entries[i].key.key; EntityGraphNode *n = M.entries[i].value; DeclInfo *decl = decl_info_of_entity(e); @@ -1838,7 +1836,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info) { for_array(i, M.entries) { auto *entry = &M.entries[i]; - auto *e = cast(Entity *)entry->key.ptr; + auto *e = cast(Entity *)cast(uintptr)entry->key.key; EntityGraphNode *n = entry->value; if (e->kind == Entity_Procedure) { @@ -3072,8 +3070,7 @@ void add_import_dependency_node(Checker *c, Ast *decl, Map *M if (is_package_name_reserved(path)) { return; } - HashKey key = hash_string(path); - AstPackage **found = map_get(&c->info.packages, key); + AstPackage **found = string_map_get(&c->info.packages, path); if (found == nullptr) { for_array(pkg_index, c->info.packages.entries) { AstPackage *pkg = c->info.packages.entries[pkg_index].value; @@ -3185,8 +3182,7 @@ Array find_import_path(Checker *c, AstPackage *start, AstPackage String path = start->fullpath; - HashKey key = hash_string(path); - AstPackage **found = map_get(&c->info.packages, key); + AstPackage **found = string_map_get(&c->info.packages, path); if (found) { AstPackage *pkg = *found; GB_ASSERT(pkg != nullptr); @@ -3248,8 +3244,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { scope = intrinsics_pkg->scope; intrinsics_pkg->used = true; } else { - HashKey key = hash_string(id->fullpath); - AstPackage **found = map_get(pkgs, key); + AstPackage **found = string_map_get(pkgs, id->fullpath); if (found == nullptr) { for_array(pkg_index, pkgs->entries) { AstPackage *pkg = pkgs->entries[pkg_index].value; @@ -3398,8 +3393,7 @@ bool collect_checked_packages_from_decl_list(Checker *c, Array const &dec Ast *decl = decls[i]; switch (decl->kind) { case_ast_node(id, ImportDecl, decl); - HashKey key = hash_string(id->fullpath); - AstPackage **found = map_get(&c->info.packages, key); + AstPackage **found = string_map_get(&c->info.packages, id->fullpath); if (found == nullptr) { continue; } @@ -3907,8 +3901,7 @@ void check_parsed_files(Checker *c) { AstPackage *p = c->parser->packages[i]; Scope *scope = create_scope_from_package(&c->init_ctx, p); p->decl_info = make_decl_info(c->allocator, scope, c->init_ctx.decl); - HashKey key = hash_string(p->fullpath); - map_set(&c->info.packages, key, p); + string_map_set(&c->info.packages, p->fullpath, p); if (scope->flags&ScopeFlag_Init) { c->info.init_scope = scope; @@ -3932,8 +3925,7 @@ void check_parsed_files(Checker *c) { for_array(j, pkg->files) { AstFile *f = pkg->files[j]; create_scope_from_file(&ctx, f); - HashKey key = hash_string(f->fullpath); - map_set(&c->info.files, key, f); + string_map_set(&c->info.files, f->fullpath, f); add_curr_ast_file(&ctx, f); check_collect_entities(&ctx, f->decls); @@ -3978,7 +3970,7 @@ void check_parsed_files(Checker *c) { for_array(i, c->info.untyped.entries) { auto *entry = &c->info.untyped.entries[i]; HashKey key = entry->key; - Ast *expr = cast(Ast *)key.ptr; + Ast *expr = cast(Ast *)cast(uintptr)key.key; ExprInfo *info = &entry->value; if (info != nullptr && expr != nullptr) { if (is_type_typed(info->type)) { diff --git a/src/checker.hpp b/src/checker.hpp index bd36971df..4834187da 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -172,7 +172,7 @@ struct Scope { Scope * next; Scope * first_child; Scope * last_child; - Map elements; // Key: String + StringMap elements; Array delayed_directives; Array delayed_imports; @@ -238,9 +238,9 @@ struct CheckerInfo { Map untyped; // Key: Ast * | Expression -> ExprInfo // NOTE(bill): This needs to be a map and not on the Ast // as it needs to be iterated across - Map files; // Key: String (full path) - Map packages; // Key: String (full path) - Map foreigns; // Key: String + StringMap files; // Key (full path) + StringMap packages; // Key (full path) + StringMap foreigns; Array definitions; Array entities; Array variable_init_order; @@ -346,9 +346,9 @@ isize type_info_index (CheckerInfo *i, Type *type, bool error_on_f Entity *entity_of_node(Ast *expr); -Entity *scope_lookup_current(Scope *s, String name); -Entity *scope_lookup (Scope *s, String name); -void scope_lookup_parent (Scope *s, String name, Scope **scope_, Entity **entity_); +Entity *scope_lookup_current(Scope *s, String const &name); +Entity *scope_lookup (Scope *s, String const &name); +void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_); Entity *scope_insert (Scope *s, Entity *entity); diff --git a/src/common.cpp b/src/common.cpp index 8f91739a4..ba9f297a3 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -340,13 +340,6 @@ void mul_overflow_u64(u64 x, u64 y, u64 *lo, u64 *hi) { -#include "map.cpp" -#include "ptr_set.cpp" -#include "string_set.cpp" -#include "priority_queue.cpp" -#include "thread_pool.cpp" - - gb_global String global_module_path = {0}; gb_global bool global_module_path_set = false; @@ -465,6 +458,57 @@ GB_ALLOCATOR_PROC(arena_allocator_proc) { + +#include "string_map.cpp" +#include "map.cpp" +#include "ptr_set.cpp" +#include "string_set.cpp" +#include "priority_queue.cpp" +#include "thread_pool.cpp" + + +struct StringIntern { + isize len; + StringIntern *next; + char str[1]; +}; + +Map string_intern_map = {}; // Key: u64 +Arena string_intern_arena = {}; + +char const *string_intern(char const *text, isize len) { + u64 hash = gb_fnv64a(text, len); + u64 key = hash ? hash : 1; + StringIntern **found = map_get(&string_intern_map, hash_integer(key)); + if (found) { + for (StringIntern *it = *found; it != nullptr; it = it->next) { + if (it->len == len && gb_strncmp(it->str, (char *)text, len) == 0) { + return it->str; + } + } + } + + StringIntern *new_intern = cast(StringIntern *)arena_alloc(&string_intern_arena, gb_offset_of(StringIntern, str) + len + 1, gb_align_of(StringIntern)); + new_intern->len = len; + new_intern->next = found ? *found : nullptr; + gb_memmove(new_intern->str, text, len); + new_intern->str[len] = 0; + map_set(&string_intern_map, hash_integer(key), new_intern); + return new_intern->str; +} + +char const *string_intern(String const &string) { + return string_intern(cast(char const *)string.text, string.len); +} + +void init_string_interner(void) { + map_init(&string_intern_map, heap_allocator()); + arena_init(&string_intern_arena, heap_allocator()); +} + + + + i32 next_pow2(i32 n) { if (n <= 0) { return 0; diff --git a/src/exact_value.cpp b/src/exact_value.cpp index f4d2e60de..1473319cc 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -69,7 +69,10 @@ HashKey hash_exact_value(ExactValue v) { case ExactValue_Bool: return hash_integer(u64(v.value_bool)); case ExactValue_String: - return hash_string(v.value_string); + { + char const *str = string_intern(v.value_string); + return hash_pointer(str); + } case ExactValue_Integer: { HashKey key = hashing_proc(big_int_ptr(&v.value_integer), v.value_integer.len * gb_size_of(u64)); diff --git a/src/ir.cpp b/src/ir.cpp index 2cc7270cb..e8ab09ea5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20,7 +20,7 @@ struct irModule { PtrSet min_dep_set; Map values; // Key: Entity * - Map members; // Key: String + StringMap members; Map entity_names; // Key: Entity * of the typename Map debug_info; // Key: Unique pointer Map anonymous_proc_lits; // Key: Ast * @@ -37,8 +37,8 @@ struct irModule { // NOTE(bill): To prevent strings from being copied a lot // Mainly used for file names - Map const_strings; // Key: String - Map const_string_byte_slices; // Key: String + StringMap const_strings; + StringMap const_string_byte_slices; Map constant_value_to_global; // Key: irValue * @@ -1509,7 +1509,7 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi irValue *value = ir_value_global(e, nullptr); value->Global.is_private = true; ir_module_add_value(m, e, value); - map_set(&m->members, hash_string(s), value); + string_map_set(&m->members, s, value); return value; } @@ -1626,7 +1626,7 @@ irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) { Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value); irValue *g = ir_value_global(e, backing_array); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); return ir_value_constant_slice(type, g, count); } @@ -1639,8 +1639,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) { irValue *global_constant_value = nullptr; { - HashKey key = hash_string(string); - irValue **found = map_get(&m->const_string_byte_slices, key); + irValue **found = string_map_get(&m->const_string_byte_slices, string); if (found != nullptr) { global_constant_value = *found; @@ -1677,7 +1676,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) { ir_module_add_value(m, entity, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); return g; } @@ -1760,8 +1759,8 @@ irValue *ir_add_local_for_identifier(irProcedure *proc, Ast *ident, bool zero_in name = e->Variable.link_name; } - HashKey key = hash_string(name); - irValue **prev_value = map_get(&proc->module->members, key); + StringHashKey key = string_hash_string(name); + irValue **prev_value = string_map_get(&proc->module->members, key); if (prev_value == nullptr) { ir_add_foreign_library_path(proc->module, e->Variable.foreign_library); // NOTE(bill): Don't do mutliple declarations in the IR @@ -1769,7 +1768,7 @@ irValue *ir_add_local_for_identifier(irProcedure *proc, Ast *ident, bool zero_in g->Global.name = name; g->Global.is_foreign = true; ir_module_add_value(proc->module, e, g); - map_set(&proc->module->members, key, g); + string_map_set(&proc->module->members, key, g); return g; } else { return *prev_value; @@ -1807,7 +1806,7 @@ irValue *ir_add_global_generated(irModule *m, Type *type, irValue *value) { Entity *e = alloc_entity_variable(scope, make_token_ident(name), type); irValue *g = ir_value_global(e, value); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); return g; } @@ -5162,26 +5161,26 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *ir_find_or_add_entity_string(irModule *m, String str) { - HashKey key = hash_string(str); - irValue **found = map_get(&m->const_strings, key); + StringHashKey key = string_hash_string(str); + irValue **found = string_map_get(&m->const_strings, key); if (found != nullptr) { return *found; } irValue *v = ir_value_constant(t_string, exact_value_string(str)); - map_set(&m->const_strings, key, v); + string_map_set(&m->const_strings, key, v); return v; } irValue *ir_find_or_add_entity_string_byte_slice(irModule *m, String str) { - HashKey key = hash_string(str); - irValue **found = map_get(&m->const_string_byte_slices, key); + StringHashKey key = string_hash_string(str); + irValue **found = string_map_get(&m->const_string_byte_slices, key); if (found != nullptr) { return *found; } Type *t = t_u8_slice; irValue *v = ir_value_constant(t, exact_value_string(str)); - map_set(&m->const_string_byte_slices, key, v); + string_map_set(&m->const_string_byte_slices, key, v); return v; } @@ -6337,7 +6336,7 @@ irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, i if (proc != nullptr) { array_add(&proc->children, &value->Proc); } else { - map_set(&m->members, hash_string(name), value); + string_map_set(&m->members, name, value); } map_set(&m->anonymous_proc_lits, hash_pointer(expr), value); @@ -6384,7 +6383,7 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) { } irValue *t = ir_value_type_name(name, e->type); ir_module_add_value(m, e, t); - map_set(&m->members, hash_string(name), t); + string_map_set(&m->members, name, t); // if (bt->kind == Type_Struct) { // Scope *s = bt->Struct.scope; @@ -9196,8 +9195,8 @@ void ir_build_constant_value_decl(irProcedure *proc, AstValueDecl *vd) { name = e->Procedure.link_name; } - HashKey key = hash_string(name); - irValue **prev_value = map_get(&proc->module->members, key); + StringHashKey key = string_hash_string(name); + irValue **prev_value = string_map_get(&proc->module->members, key); if (prev_value != nullptr) { // NOTE(bill): Don't do mutliple declarations in the IR return; @@ -9210,7 +9209,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstValueDecl *vd) { value->Proc.inlining = pl->inlining; if (value->Proc.is_foreign || value->Proc.is_export) { - map_set(&proc->module->members, key, value); + string_map_set(&proc->module->members, key, value); } else { array_add(&proc->children, &value->Proc); } @@ -9721,7 +9720,6 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { mangled_name.len = gb_string_length(str); } - HashKey key = hash_string(mangled_name); ir_add_entity_name(m, e, mangled_name); irValue *g = ir_value_global(e, value); @@ -9733,7 +9731,7 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { g->Global.is_internal = true; } ir_module_add_value(proc->module, e, g); - map_set(&proc->module->members, key, g); + string_map_set(&proc->module->members, mangled_name, g); } return; } @@ -11083,15 +11081,15 @@ void ir_init_module(irModule *m, Checker *c) { } map_init(&m->values, heap_allocator()); - map_init(&m->members, heap_allocator()); + string_map_init(&m->members, heap_allocator()); map_init(&m->debug_info, heap_allocator()); map_init(&m->entity_names, heap_allocator()); map_init(&m->anonymous_proc_lits, heap_allocator()); array_init(&m->procs, heap_allocator()); array_init(&m->procs_to_generate, heap_allocator()); array_init(&m->foreign_library_paths, heap_allocator()); - map_init(&m->const_strings, heap_allocator()); - map_init(&m->const_string_byte_slices, heap_allocator()); + string_map_init(&m->const_strings, heap_allocator()); + string_map_init(&m->const_string_byte_slices, heap_allocator()); map_init(&m->constant_value_to_global, heap_allocator()); // Default states @@ -11108,7 +11106,7 @@ void ir_init_module(irModule *m, Checker *c) { irValue *g = ir_value_global(e, nullptr); g->Global.is_private = true; ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_data = g; } @@ -11145,7 +11143,7 @@ void ir_init_module(irModule *m, Checker *c) { alloc_type_array(t_type_info_ptr, count)); irValue *g = ir_value_global(e, nullptr); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_member_types = g; } { @@ -11154,7 +11152,7 @@ void ir_init_module(irModule *m, Checker *c) { alloc_type_array(t_string, count)); irValue *g = ir_value_global(e, nullptr); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_member_names = g; } { @@ -11163,7 +11161,7 @@ void ir_init_module(irModule *m, Checker *c) { alloc_type_array(t_uintptr, count)); irValue *g = ir_value_global(e, nullptr); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_member_offsets = g; } @@ -11173,7 +11171,7 @@ void ir_init_module(irModule *m, Checker *c) { alloc_type_array(t_bool, count)); irValue *g = ir_value_global(e, nullptr); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_member_usings = g; } @@ -11183,7 +11181,7 @@ void ir_init_module(irModule *m, Checker *c) { alloc_type_array(t_string, count)); irValue *g = ir_value_global(e, nullptr); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); ir_global_type_info_member_tags = g; } } @@ -11226,12 +11224,12 @@ void ir_init_module(irModule *m, Checker *c) { void ir_destroy_module(irModule *m) { map_destroy(&m->values); - map_destroy(&m->members); + string_map_destroy(&m->members); map_destroy(&m->entity_names); map_destroy(&m->anonymous_proc_lits); map_destroy(&m->debug_info); - map_destroy(&m->const_strings); - map_destroy(&m->const_string_byte_slices); + string_map_destroy(&m->const_strings); + string_map_destroy(&m->const_string_byte_slices); map_destroy(&m->constant_value_to_global); array_free(&m->procs); array_free(&m->procs_to_generate); @@ -12020,7 +12018,7 @@ void ir_gen_tree(irGen *s) { array_add(&global_variables, var); ir_module_add_value(m, e, g); - map_set(&m->members, hash_string(name), g); + string_map_set(&m->members, name, g); } for_array(i, info->entities) { @@ -12110,9 +12108,9 @@ void ir_gen_tree(irGen *s) { p->Proc.is_export = e->Procedure.is_export; ir_module_add_value(m, e, p); - HashKey hash_name = hash_string(name); - if (map_get(&m->members, hash_name) == nullptr) { - map_set(&m->members, hash_name, p); + StringHashKey hash_name = string_hash_string(name); + if (string_map_get(&m->members, hash_name) == nullptr) { + string_map_set(&m->members, hash_name, p); } break; } @@ -12173,7 +12171,7 @@ void ir_gen_tree(irGen *s) { p->Proc.is_startup = true; map_set(&m->values, hash_entity(e), p); - map_set(&m->members, hash_string(name), p); + string_map_set(&m->members, name, p); irProcedure *proc = &p->Proc; proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea? @@ -12254,7 +12252,7 @@ void ir_gen_tree(irGen *s) { p->Proc.is_startup = true; map_set(&m->values, hash_entity(e), p); - map_set(&m->members, hash_string(name), p); + string_map_set(&m->members, name, p); irProcedure *proc = &p->Proc; proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea? @@ -12355,7 +12353,7 @@ void ir_gen_tree(irGen *s) { m->entry_point_entity = e; map_set(&m->values, hash_entity(e), p); - map_set(&m->members, hash_string(name), p); + string_map_set(&m->members, name, p); irProcedure *proc = &p->Proc; // proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? @@ -12386,7 +12384,7 @@ void ir_gen_tree(irGen *s) { p->Proc.is_startup = true; map_set(&m->values, hash_entity(e), p); - map_set(&m->members, hash_string(name), p); + string_map_set(&m->members, name, p); irProcedure *proc = &p->Proc; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 6d7148eab..2d5a2e1dd 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -2651,16 +2651,16 @@ void print_llvm_ir(irGen *ir) { ir_write_str_lit(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) #3 \n"); - if (map_get(&m->members, hash_string(str_lit("llvm.bswap.i16"))) == nullptr) { + if (string_map_get(&m->members, str_lit("llvm.bswap.i16")) == nullptr) { ir_write_str_lit(f, "declare i16 @llvm.bswap.i16(i16) \n"); } - if (map_get(&m->members, hash_string(str_lit("llvm.bswap.i32"))) == nullptr) { + if (string_map_get(&m->members, str_lit("llvm.bswap.i32")) == nullptr) { ir_write_str_lit(f, "declare i32 @llvm.bswap.i32(i32) \n"); } - if (map_get(&m->members, hash_string(str_lit("llvm.bswap.i64"))) == nullptr) { + if (string_map_get(&m->members, str_lit("llvm.bswap.i64")) == nullptr) { ir_write_str_lit(f, "declare i64 @llvm.bswap.i64(i64) \n"); } - if (map_get(&m->members, hash_string(str_lit("llvm.bswap.i128"))) == nullptr) { + if (string_map_get(&m->members, str_lit("llvm.bswap.i128")) == nullptr) { ir_write_str_lit(f, "declare i128 @llvm.bswap.i128(i128) \n"); } ir_write_byte(f, '\n'); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 302f7af91..954e6368d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1630,17 +1630,17 @@ void lb_add_entity(lbModule *m, Entity *e, lbValue val) { } void lb_add_member(lbModule *m, String const &name, lbValue val) { if (name.len > 0) { - map_set(&m->members, hash_string(name), val); + string_map_set(&m->members, name, val); } } -void lb_add_member(lbModule *m, HashKey const &key, lbValue val) { - map_set(&m->members, key, val); +void lb_add_member(lbModule *m, StringHashKey const &key, lbValue val) { + string_map_set(&m->members, key, val); } void lb_add_procedure_value(lbModule *m, lbProcedure *p) { if (p->entity != nullptr) { map_set(&m->procedure_values, hash_pointer(p->value), p->entity); } - map_set(&m->procedures, hash_string(p->name), p); + string_map_set(&m->procedures, p->name, p); } @@ -1688,11 +1688,11 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) { String link_name = lb_get_entity_name(m, entity); { - HashKey key = hash_string(link_name); - lbValue *found = map_get(&m->members, key); + StringHashKey key = string_hash_string(link_name); + lbValue *found = string_map_get(&m->members, key); if (found) { lb_add_entity(m, entity, *found); - lbProcedure **p_found = map_get(&m->procedures, key); + lbProcedure **p_found = string_map_get(&m->procedures, key); GB_ASSERT(p_found != nullptr); return *p_found; } @@ -1824,8 +1824,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) { lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type) { { - HashKey key = hash_string(link_name); - lbValue *found = map_get(&m->members, key); + lbValue *found = string_map_get(&m->members, link_name); GB_ASSERT(found == nullptr); } @@ -2493,8 +2492,7 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { name = e->Procedure.link_name; } - HashKey key = hash_string(name); - lbValue *prev_value = map_get(&p->module->members, key); + lbValue *prev_value = string_map_get(&p->module->members, name); if (prev_value != nullptr) { // NOTE(bill): Don't do mutliple declarations in the IR return; @@ -2513,7 +2511,7 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { if (p != nullptr) { array_add(&p->children, nested_proc); } else { - map_set(&p->module->members, hash_string(name), value); + string_map_set(&p->module->members, name, value); } } } @@ -4140,8 +4138,8 @@ lbValue lb_emit_clamp(lbProcedure *p, Type *t, lbValue x, lbValue min, lbValue m LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) { - HashKey key = hash_string(str); - LLVMValueRef *found = map_get(&m->const_strings, key); + StringHashKey key = string_hash_string(str); + LLVMValueRef *found = string_map_get(&m->const_strings, key); if (found != nullptr) { return *found; } else { @@ -4162,7 +4160,7 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) { LLVMSetInitializer(global_data, data); LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2); - map_set(&m->const_strings, key, ptr); + string_map_set(&m->const_strings, key, ptr); return ptr; } } @@ -8399,7 +8397,7 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A if (parent != nullptr) { array_add(&parent->children, p); } else { - map_set(&m->members, hash_string(name), value); + string_map_set(&m->members, name, value); } map_set(&m->anonymous_proc_lits, hash_pointer(expr), p); @@ -10187,10 +10185,10 @@ void lb_init_module(lbModule *m, Checker *c) { gbAllocator a = heap_allocator(); map_init(&m->types, a); map_init(&m->values, a); - map_init(&m->members, a); + string_map_init(&m->members, a); map_init(&m->procedure_values, a); - map_init(&m->procedures, a); - map_init(&m->const_strings, a); + string_map_init(&m->procedures, a); + string_map_init(&m->const_strings, a); map_init(&m->anonymous_proc_lits, a); array_init(&m->procedures_to_generate, a); array_init(&m->foreign_library_paths, a); @@ -10342,7 +10340,7 @@ lbValue lb_generate_array(lbModule *m, Type *elem_type, i64 count, String prefix g.type = alloc_type_pointer(t); LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g.value, LLVMInternalLinkage); - map_set(&m->members, hash_string(s), g); + string_map_set(&m->members, s, g); return g; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 02284b064..ee40ea789 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -62,11 +62,11 @@ struct lbModule { Map types; // Key: Type * Map values; // Key: Entity * - Map members; // Key: String - Map procedures; // Key: String + StringMap members; + StringMap procedures; Map procedure_values; // Key: LLVMValueRef - Map const_strings; // Key: String + StringMap const_strings; Map anonymous_proc_lits; // Key: Ast * diff --git a/src/main.cpp b/src/main.cpp index c2c3ed2b5..e467ae95b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -919,7 +919,7 @@ bool parse_build_flags(Array args) { break; } - HashKey key = hash_string(name); + HashKey key = hash_pointer(string_intern(name)); if (map_get(&build_context.defined_values, key) != nullptr) { gb_printf_err("Defined constant '%.*s' already exists\n", LIT(name)); @@ -1431,6 +1431,7 @@ int main(int arg_count, char const **arg_ptr) { defer (timings_destroy(timings)); init_string_buffer_memory(); + init_string_interner(); init_global_error_collector(); global_big_int_init(); arena_init(&global_ast_arena, heap_allocator()); diff --git a/src/map.cpp b/src/map.cpp index 03ac924fe..ae6bf9f74 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -13,91 +13,42 @@ struct MapFindResult { isize entry_index; }; -enum HashKeyKind { - HashKey_Default, - HashKey_String, - HashKey_Ptr, - HashKey_PtrAndId, -}; - -struct PtrAndId { - void *ptr; - u64 id; -}; struct HashKey { - HashKeyKind kind; - // u128 key; - u64 key; - union { - String string; // if String, s.len > 0 - void * ptr; - PtrAndId ptr_and_id; - }; + u64 key; }; +GB_STATIC_ASSERT(gb_size_of(u64) >= gb_size_of(void *)); gb_inline HashKey hashing_proc(void const *data, isize len) { - HashKey h = {HashKey_Default}; - h.kind = HashKey_Default; + HashKey h = {}; // h.key = u128_from_u64(gb_fnv64a(data, len)); h.key = gb_fnv64a(data, len); return h; } -gb_inline HashKey hash_string(String s) { - HashKey h = hashing_proc(s.text, s.len); - h.kind = HashKey_String; - h.string = s; +gb_inline HashKey hash_pointer(void const *ptr) { + HashKey h = {}; + h.key = cast(u64)cast(uintptr)ptr; return h; } -gb_inline HashKey hash_pointer(void *ptr) { - HashKey h = {HashKey_Ptr}; - h.key = cast(u64)cast(uintptr)ptr; - // h.key = gb_fnv64a(&ptr, gb_size_of(void *)); - h.ptr = ptr; - return h; -} -gb_inline HashKey hash_ptr_and_id(void *ptr, u64 id) { - HashKey h = {HashKey_PtrAndId}; - h.key = cast(u64)cast(uintptr)ptr; - // h.key = gb_fnv64a(&ptr, gb_size_of(void *)); - h.ptr_and_id.ptr = ptr; - h.ptr_and_id.id = id; - return h; -} gb_inline HashKey hash_integer(u64 u) { - HashKey h = {HashKey_Default}; + HashKey h = {}; h.key = u; return h; } gb_inline HashKey hash_f64(f64 f) { - HashKey h = {HashKey_Default}; + HashKey h = {}; h.key = bit_cast(f); return h; } -bool hash_key_equal(HashKey a, HashKey b) { - if (a.key == b.key) { - // NOTE(bill): If two string's hashes collide, compare the strings themselves - if (a.kind == HashKey_String) { - if (b.kind == HashKey_String) { - return a.string == b.string; - } - return false; - } else if (a.kind == HashKey_PtrAndId) { - if (b.kind == HashKey_PtrAndId) { - return a.ptr_and_id.id == b.ptr_and_id.id; - } - return false; - } - return true; - } - return false; +gb_inline bool hash_key_equal(HashKey a, HashKey b) { + return a.key == b.key; } -bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); } -bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); } +gb_inline bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); } +gb_inline bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); } #endif @@ -117,23 +68,23 @@ struct Map { template void map_init (Map *h, gbAllocator a, isize capacity = 16); template void map_destroy (Map *h); -template T * map_get (Map *h, HashKey key); -template void map_set (Map *h, HashKey key, T const &value); -template void map_remove (Map *h, HashKey key); +template T * map_get (Map *h, HashKey const &key); +template void map_set (Map *h, HashKey const &key, T const &value); +template void map_remove (Map *h, HashKey const &key); template void map_clear (Map *h); template void map_grow (Map *h); template void map_rehash (Map *h, isize new_count); #if MAP_ENABLE_MULTI_MAP // Mutlivalued map procedure -template MapEntry * multi_map_find_first(Map *h, HashKey key); +template MapEntry * multi_map_find_first(Map *h, HashKey const &key); template MapEntry * multi_map_find_next (Map *h, MapEntry *e); -template isize multi_map_count (Map *h, HashKey key); -template void multi_map_get_all (Map *h, HashKey key, T *items); -template void multi_map_insert (Map *h, HashKey key, T const &value); -template void multi_map_remove (Map *h, HashKey key, MapEntry *e); -template void multi_map_remove_all(Map *h, HashKey key); +template isize multi_map_count (Map *h, HashKey const &key); +template void multi_map_get_all (Map *h, HashKey const &key, T *items); +template void multi_map_insert (Map *h, HashKey const &key, T const &value); +template void multi_map_remove (Map *h, HashKey const &key, MapEntry *e); +template void multi_map_remove_all(Map *h, HashKey const &key); #endif template @@ -149,7 +100,7 @@ gb_inline void map_destroy(Map *h) { } template -gb_internal isize map__add_entry(Map *h, HashKey key) { +gb_internal isize map__add_entry(Map *h, HashKey const &key) { MapEntry e = {}; e.key = key; e.next = -1; @@ -158,7 +109,7 @@ gb_internal isize map__add_entry(Map *h, HashKey key) { } template -gb_internal MapFindResult map__find(Map *h, HashKey key) { +gb_internal MapFindResult map__find(Map *h, HashKey const &key) { MapFindResult fr = {-1, -1, -1}; if (h->hashes.count > 0) { // fr.hash_index = u128_to_i64(key.key % u128_from_i64(h->hashes.count)); @@ -240,7 +191,7 @@ void map_rehash(Map *h, isize new_count) { } template -gb_inline T *map_get(Map *h, HashKey key) { +T *map_get(Map *h, HashKey const &key) { isize index = map__find(h, key).entry_index; if (index >= 0) { return &h->entries[index].value; @@ -249,7 +200,7 @@ gb_inline T *map_get(Map *h, HashKey key) { } template -void map_set(Map *h, HashKey key, T const &value) { +void map_set(Map *h, HashKey const &key, T const &value) { isize index; MapFindResult fr; if (h->hashes.count == 0) { @@ -275,7 +226,7 @@ void map_set(Map *h, HashKey key, T const &value) { template -void map__erase(Map *h, MapFindResult fr) { +void map__erase(Map *h, MapFindResult const &fr) { MapFindResult last; if (fr.entry_prev < 0) { h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; @@ -296,7 +247,7 @@ void map__erase(Map *h, MapFindResult fr) { } template -void map_remove(Map *h, HashKey key) { +void map_remove(Map *h, HashKey const &key) { MapFindResult fr = map__find(h, key); if (fr.entry_index >= 0) { map__erase(h, fr); @@ -312,7 +263,7 @@ gb_inline void map_clear(Map *h) { #if MAP_ENABLE_MULTI_MAP template -MapEntry *multi_map_find_first(Map *h, HashKey key) { +MapEntry *multi_map_find_first(Map *h, HashKey const &key) { isize i = map__find(h, key).entry_index; if (i < 0) { return nullptr; @@ -333,7 +284,7 @@ MapEntry *multi_map_find_next(Map *h, MapEntry *e) { } template -isize multi_map_count(Map *h, HashKey key) { +isize multi_map_count(Map *h, HashKey const &key) { isize count = 0; MapEntry *e = multi_map_find_first(h, key); while (e != nullptr) { @@ -344,7 +295,7 @@ isize multi_map_count(Map *h, HashKey key) { } template -void multi_map_get_all(Map *h, HashKey key, T *items) { +void multi_map_get_all(Map *h, HashKey const &key, T *items) { isize i = 0; MapEntry *e = multi_map_find_first(h, key); while (e != nullptr) { @@ -354,7 +305,7 @@ void multi_map_get_all(Map *h, HashKey key, T *items) { } template -void multi_map_insert(Map *h, HashKey key, T const &value) { +void multi_map_insert(Map *h, HashKey const &key, T const &value) { MapFindResult fr; isize i; if (h->hashes.count == 0) { @@ -377,7 +328,7 @@ void multi_map_insert(Map *h, HashKey key, T const &value) { } template -void multi_map_remove(Map *h, HashKey key, MapEntry *e) { +void multi_map_remove(Map *h, HashKey const &key, MapEntry *e) { MapFindResult fr = map__find_from_entry(h, e); if (fr.entry_index >= 0) { map__erase(h, fr); @@ -385,7 +336,7 @@ void multi_map_remove(Map *h, HashKey key, MapEntry *e) { } template -void multi_map_remove_all(Map *h, HashKey key) { +void multi_map_remove_all(Map *h, HashKey const &key) { while (map_get(h, key) != nullptr) { map_remove(h, key); } diff --git a/src/parser.cpp b/src/parser.cpp index b05f7df2f..e0cd60d79 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -4310,7 +4310,7 @@ void destroy_ast_file(AstFile *f) { bool init_parser(Parser *p) { GB_ASSERT(p != nullptr); string_set_init(&p->imported_files, heap_allocator()); - map_init(&p->package_map, heap_allocator()); + string_map_init(&p->package_map, heap_allocator()); array_init(&p->packages, heap_allocator()); array_init(&p->package_imports, heap_allocator()); gb_mutex_init(&p->file_add_mutex); @@ -4336,7 +4336,7 @@ void destroy_parser(Parser *p) { array_free(&p->packages); array_free(&p->package_imports); string_set_destroy(&p->imported_files); - map_destroy(&p->package_map); + string_map_destroy(&p->package_map); gb_mutex_destroy(&p->file_add_mutex); gb_mutex_destroy(&p->file_decl_mutex); } @@ -4346,8 +4346,8 @@ void parser_add_package(Parser *p, AstPackage *pkg) { pkg->id = p->packages.count+1; array_add(&p->packages, pkg); if (pkg->name.len > 0) { - HashKey key = hash_string(pkg->name); - auto found = map_get(&p->package_map, key); + StringHashKey key = string_hash_string(pkg->name); + auto found = string_map_get(&p->package_map, key); if (found) { GB_ASSERT(pkg->files.count > 0); AstFile *f = pkg->files[0]; @@ -4356,7 +4356,7 @@ void parser_add_package(Parser *p, AstPackage *pkg) { TokenPos pos = (*found)->files[0]->package_token.pos; error_line("\tpreviously declared at %.*s(%td:%td)\n", LIT(pos.file), pos.line, pos.column); } else { - map_set(&p->package_map, key, pkg); + string_map_set(&p->package_map, key, pkg); } } } diff --git a/src/parser.hpp b/src/parser.hpp index 9c55bf2f7..1b236b921 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -131,16 +131,16 @@ struct AstPackage { struct Parser { - String init_fullpath; - StringSet imported_files; // fullpath - Map package_map; // Key: String (package name) - Array packages; - Array package_imports; - isize file_to_process_count; - isize total_token_count; - isize total_line_count; - gbMutex file_add_mutex; - gbMutex file_decl_mutex; + String init_fullpath; + StringSet imported_files; // fullpath + StringMap package_map; // Key(package name) + Array packages; + Array package_imports; + isize file_to_process_count; + isize total_token_count; + isize total_line_count; + gbMutex file_add_mutex; + gbMutex file_decl_mutex; }; diff --git a/src/query_data.cpp b/src/query_data.cpp index b670ea958..763665e61 100644 --- a/src/query_data.cpp +++ b/src/query_data.cpp @@ -918,7 +918,7 @@ void generate_and_print_query_data_go_to_definitions(Checker *c) { } - AstFile **use_file_found = map_get(&c->info.files, hash_string(pos.file)); + AstFile **use_file_found = string_map_get(&c->info.files, pos.file); GB_ASSERT(use_file_found != nullptr); AstFile *use_file = *use_file_found; GB_ASSERT(use_file != nullptr); @@ -1008,7 +1008,7 @@ void generate_and_print_query_data_go_to_definitions(Checker *c) { AstFile *def_file = e->file; if (def_file == nullptr) { - auto *def_file_found = map_get(&c->info.files, hash_string(e->token.pos.file)); + auto *def_file_found = string_map_get(&c->info.files, e->token.pos.file); if (def_file_found == nullptr) { continue; } diff --git a/src/string_map.cpp b/src/string_map.cpp new file mode 100644 index 000000000..485048154 --- /dev/null +++ b/src/string_map.cpp @@ -0,0 +1,257 @@ +// NOTE(bill): This util stuff is the same for every `Map` +struct StringMapFindResult { + isize hash_index; + isize entry_prev; + isize entry_index; +}; + +struct StringHashKey { + u64 hash; + String string; +}; + +StringHashKey string_hashing_proc(void const *data, isize len) { + StringHashKey h = {}; + h.hash = gb_fnv64a(data, len); + h.string.text = (u8 *)data; + h.string.len = len; + return h; +} + +gb_inline StringHashKey string_hash_string(String const &s) { + return string_hashing_proc(s.text, s.len); +} + + +bool string_hash_key_equal(StringHashKey a, StringHashKey b) { + if (a.hash == b.hash) { + // NOTE(bill): If two string's hashes collide, compare the strings themselves + return a.string == b.string; + } + return false; +} +bool operator==(StringHashKey a, StringHashKey b) { return string_hash_key_equal(a, b); } +bool operator!=(StringHashKey a, StringHashKey b) { return !string_hash_key_equal(a, b); } + +template +struct StringMapEntry { + StringHashKey key; + isize next; + T value; +}; + +template +struct StringMap { + Array hashes; + Array > entries; +}; + + +template void string_map_init (StringMap *h, gbAllocator a, isize capacity = 16); +template void string_map_destroy (StringMap *h); + +template T * string_map_get (StringMap *h, char const *key); +template T * string_map_get (StringMap *h, String const &key); +template T * string_map_get (StringMap *h, StringHashKey const &key); + +template void string_map_set (StringMap *h, StringHashKey const &key, T const &value); +template void string_map_set (StringMap *h, String const &key, T const &value); +template void string_map_set (StringMap *h, char const *key, T const &value); + +template void string_map_remove (StringMap *h, StringHashKey const &key); +template void string_map_clear (StringMap *h); +template void string_map_grow (StringMap *h); +template void string_map_rehash (StringMap *h, isize new_count); + +template +gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { + array_init(&h->hashes, a, 0, capacity); + array_init(&h->entries, a, 0, capacity); +} + +template +gb_inline void string_map_destroy(StringMap *h) { + array_free(&h->entries); + array_free(&h->hashes); +} + +template +gb_internal isize string_map__add_entry(StringMap *h, StringHashKey const &key) { + StringMapEntry e = {}; + e.key = key; + e.next = -1; + array_add(&h->entries, e); + return h->entries.count-1; +} + +template +gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey const &key) { + StringMapFindResult fr = {-1, -1, -1}; + if (h->hashes.count > 0) { + fr.hash_index = key.hash % h->hashes.count; + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index >= 0) { + if (string_hash_key_equal(h->entries[fr.entry_index].key, key)) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = h->entries[fr.entry_index].next; + } + } + return fr; +} + +template +gb_internal StringMapFindResult string_map__find_from_entry(StringMap *h, StringMapEntry *e) { + StringMapFindResult fr = {-1, -1, -1}; + if (h->hashes.count > 0) { + fr.hash_index = e->key.hash % h->hashes.count; + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index >= 0) { + if (&h->entries[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = h->entries[fr.entry_index].next; + } + } + return fr; +} + +template +gb_internal b32 string_map__full(StringMap *h) { + return 0.75f * h->hashes.count <= h->entries.count; +} + +#define STRING_MAP_ARRAY_GROW_FORMULA(x) (4*(x) + 7) +GB_STATIC_ASSERT(STRING_MAP_ARRAY_GROW_FORMULA(0) > 0); + +template +gb_inline void string_map_grow(StringMap *h) { + isize new_count = STRING_MAP_ARRAY_GROW_FORMULA(h->entries.count); + string_map_rehash(h, new_count); +} + +template +void string_map_rehash(StringMap *h, isize new_count) { + isize i, j; + StringMap nh = {}; + string_map_init(&nh, h->hashes.allocator); + array_resize(&nh.hashes, new_count); + array_reserve(&nh.entries, h->entries.count); + for (i = 0; i < new_count; i++) { + nh.hashes[i] = -1; + } + for (i = 0; i < h->entries.count; i++) { + StringMapEntry *e = &h->entries[i]; + StringMapFindResult fr; + if (nh.hashes.count == 0) { + string_map_grow(&nh); + } + fr = string_map__find(&nh, e->key); + j = string_map__add_entry(&nh, e->key); + if (fr.entry_prev < 0) { + nh.hashes[fr.hash_index] = j; + } else { + nh.entries[fr.entry_prev].next = j; + } + nh.entries[j].next = fr.entry_index; + nh.entries[j].value = e->value; + if (string_map__full(&nh)) { + string_map_grow(&nh); + } + } + string_map_destroy(h); + *h = nh; +} + +template +T *string_map_get(StringMap *h, StringHashKey const &key) { + isize index = string_map__find(h, key).entry_index; + if (index >= 0) { + return &h->entries[index].value; + } + return nullptr; +} + +template +gb_inline T *string_map_get(StringMap *h, String const &key) { + return string_map_get(h, string_hash_string(key)); +} + +template +gb_inline T *string_map_get(StringMap *h, char const *key) { + return string_map_get(h, string_hash_string(make_string_c(key))); +} + +template +void string_map_set(StringMap *h, StringHashKey const &key, T const &value) { + isize index; + StringMapFindResult fr; + if (h->hashes.count == 0) { + string_map_grow(h); + } + fr = string_map__find(h, key); + if (fr.entry_index >= 0) { + index = fr.entry_index; + } else { + index = string_map__add_entry(h, key); + if (fr.entry_prev >= 0) { + h->entries[fr.entry_prev].next = index; + } else { + h->hashes[fr.hash_index] = index; + } + } + h->entries[index].value = value; + + if (string_map__full(h)) { + string_map_grow(h); + } +} + +template +gb_inline void string_map_set(StringMap *h, String const &key, T const &value) { + string_map_set(h, string_hash_string(key), value); +} + +template +gb_inline void string_map_set(StringMap *h, char const *key, T const &value) { + string_map_set(h, string_hash_string(make_string_c(key)), value); +} + + +template +void string_map__erase(StringMap *h, StringMapFindResult const &fr) { + StringMapFindResult last; + if (fr.entry_prev < 0) { + h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; + } else { + h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; + } + if (fr.entry_index == h->entries.count-1) { + array_pop(&h->entries); + return; + } + h->entries[fr.entry_index] = h->entries[h->entries.count-1]; + last = string_map__find(h, h->entries[fr.entry_index].key); + if (last.entry_prev >= 0) { + h->entries[last.entry_prev].next = fr.entry_index; + } else { + h->hashes[last.hash_index] = fr.entry_index; + } +} + +template +void string_map_remove(StringMap *h, StringHashKey const &key) { + StringMapFindResult fr = string_map__find(h, key); + if (fr.entry_index >= 0) { + string_map__erase(h, fr); + } +} + +template +gb_inline void string_map_clear(StringMap *h) { + array_clear(&h->hashes); + array_clear(&h->entries); +} + diff --git a/src/string_set.cpp b/src/string_set.cpp index a6700839d..671b2c9ff 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -5,9 +5,9 @@ struct StringSetFindResult { }; struct StringSetEntry { - HashKey key; - isize next; - String value; + u64 hash; + isize next; + String value; }; struct StringSet { @@ -18,9 +18,9 @@ struct StringSet { void string_set_init (StringSet *s, gbAllocator a, isize capacity = 16); void string_set_destroy(StringSet *s); -void string_set_add (StringSet *s, String str); -bool string_set_exists (StringSet *s, String str); -void string_set_remove (StringSet *s, String str); +void string_set_add (StringSet *s, String const &str); +bool string_set_exists (StringSet *s, String const &str); +void string_set_remove (StringSet *s, String const &str); void string_set_clear (StringSet *s); void string_set_grow (StringSet *s); void string_set_rehash (StringSet *s, isize new_count); @@ -36,22 +36,24 @@ gb_inline void string_set_destroy(StringSet *s) { array_free(&s->hashes); } -gb_internal isize string_set__add_entry(StringSet *s, HashKey key) { +gb_internal isize string_set__add_entry(StringSet *s, StringHashKey const &key) { StringSetEntry e = {}; - e.key = key; + e.hash = key.hash; e.next = -1; + e.value = key.string; array_add(&s->entries, e); return s->entries.count-1; } -gb_internal StringSetFindResult string_set__find(StringSet *s, HashKey key) { +gb_internal StringSetFindResult string_set__find(StringSet *s, StringHashKey const &key) { StringSetFindResult fr = {-1, -1, -1}; if (s->hashes.count > 0) { // fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count)); - fr.hash_index = key.key % s->hashes.count; + fr.hash_index = key.hash % s->hashes.count; fr.entry_index = s->hashes[fr.hash_index]; while (fr.entry_index >= 0) { - if (hash_key_equal(s->entries[fr.entry_index].key, key)) { + auto const &entry = s->entries[fr.entry_index]; + if (entry.hash == key.hash && entry.value == key.string) { return fr; } fr.entry_prev = fr.entry_index; @@ -85,8 +87,9 @@ void string_set_rehash(StringSet *s, isize new_count) { if (ns.hashes.count == 0) { string_set_grow(&ns); } - fr = string_set__find(&ns, e->key); - j = string_set__add_entry(&ns, e->key); + StringHashKey key = {e->hash, e->value}; + fr = string_set__find(&ns, key); + j = string_set__add_entry(&ns, key); if (fr.entry_prev < 0) { ns.hashes[fr.hash_index] = j; } else { @@ -102,16 +105,16 @@ void string_set_rehash(StringSet *s, isize new_count) { *s = ns; } -gb_inline bool string_set_exists(StringSet *s, String str) { - HashKey key = hash_string(str); +gb_inline bool string_set_exists(StringSet *s, String const &str) { + StringHashKey key = string_hash_string(str); isize index = string_set__find(s, key).entry_index; return index >= 0; } -void string_set_add(StringSet *s, String str) { +void string_set_add(StringSet *s, String const &str) { isize index; StringSetFindResult fr; - HashKey key = hash_string(str); + StringHashKey key = string_hash_string(str); if (s->hashes.count == 0) { string_set_grow(s); } @@ -145,8 +148,10 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { array_pop(&s->entries); return; } - s->entries[fr.entry_index] = s->entries[s->entries.count-1]; - last = string_set__find(s, s->entries[fr.entry_index].key); + auto *entry = &s->entries[fr.entry_index]; + *entry = s->entries[s->entries.count-1]; + StringHashKey key = {entry->hash, entry->value}; + last = string_set__find(s, key); if (last.entry_prev >= 0) { s->entries[last.entry_prev].next = fr.entry_index; } else { @@ -154,8 +159,8 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { } } -void string_set_remove(StringSet *s, String str) { - HashKey key = hash_string(str); +void string_set_remove(StringSet *s, String const &str) { + StringHashKey key = string_hash_string(str); StringSetFindResult fr = string_set__find(s, key); if (fr.entry_index >= 0) { string_set__erase(s, fr); diff --git a/src/types.cpp b/src/types.cpp index 52db2ee44..bf5a12e9b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2254,7 +2254,7 @@ Selection lookup_field_from_index(Type *type, i64 index) { } -Entity *scope_lookup_current(Scope *s, String name); +Entity *scope_lookup_current(Scope *s, String const &name); Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) { GB_ASSERT(type_ != nullptr);