From 015fe924b8f9a1d8cb78d307a4f8ef6791402bea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 12:28:38 +0000 Subject: Remove use of queues for procedure checking. --- src/check_expr.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ed1ddd1f1..eb9f76547 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -417,8 +417,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E CheckerContext nctx = *old_c; - nctx.procs_to_check_queue = old_c->procs_to_check_queue; - Scope *scope = create_scope(info, base_entity->scope); scope->flags |= ScopeFlag_Proc; nctx.scope = scope; @@ -566,7 +564,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } // NOTE(bill): Check the newly generated procedure body - check_procedure_later(&nctx, proc_info); + check_procedure_later(nctx.checker, proc_info); return true; } @@ -6187,7 +6185,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op decl->where_clauses_evaluated = true; if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) { - check_procedure_later(c, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); + check_procedure_later(c->checker, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); } } return data; @@ -6225,7 +6223,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op decl->where_clauses_evaluated = true; if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) { - check_procedure_later(c, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); + check_procedure_later(c->checker, e->file, e->token, decl, e->type, decl->proc_lit->ProcLit.body, decl->proc_lit->ProcLit.tags); } } return data; @@ -9447,7 +9445,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast } pl->decl = decl; - check_procedure_later(&ctx, ctx.file, empty_token, decl, type, pl->body, pl->tags); + check_procedure_later(ctx.checker, ctx.file, empty_token, decl, type, pl->body, pl->tags); } check_close_scope(&ctx); -- cgit v1.2.3 From 529383f5b17d74f66bebb8679820a69476635b6a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 15:30:04 +0000 Subject: Correct a race condition when checking the procedure body --- src/build_settings.cpp | 1 + src/check_decl.cpp | 25 ++--- src/check_expr.cpp | 23 ++++- src/checker.cpp | 224 ++++++++++++++++++++++++++++++++++--------- src/checker.hpp | 21 +++- src/llvm_backend.cpp | 6 ++ src/llvm_backend.hpp | 1 + src/llvm_backend_expr.cpp | 6 +- src/llvm_backend_general.cpp | 5 +- src/llvm_backend_proc.cpp | 3 +- src/llvm_backend_stmt.cpp | 6 +- src/main.cpp | 5 + 12 files changed, 260 insertions(+), 66 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 97b512b81..f59b5c0f7 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -291,6 +291,7 @@ struct BuildContext { bool show_error_line; bool ignore_lazy; + bool ignore_llvm_build; bool use_subsystem_windows; bool ignore_microsoft_magic; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 4e3c1b405..8f95c1a49 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1419,9 +1419,9 @@ struct ProcUsingVar { }; -gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) { +gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) { if (body == nullptr) { - return; + return false; } GB_ASSERT(body->kind == Ast_BlockStmt); @@ -1502,7 +1502,7 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de MUTEX_GUARD_BLOCK(ctx->scope->mutex) for_array(i, using_entities) { Entity *e = using_entities[i].e; Entity *uvar = using_entities[i].uvar; - Entity *prev = scope_insert(ctx->scope, uvar, false); + Entity *prev = scope_insert_no_mutex(ctx->scope, uvar); if (prev != nullptr) { error(e->token, "Namespace collision while 'using' procedure argument '%.*s' of: %.*s", LIT(e->token.string), LIT(prev->token.string)); error_line("%.*s != %.*s\n", LIT(uvar->token.string), LIT(prev->token.string)); @@ -1514,7 +1514,7 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated); if (!where_clause_ok) { // NOTE(bill, 2019-08-31): Don't check the body as the where clauses failed - return; + return false; } check_open_scope(ctx, body); @@ -1526,7 +1526,12 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de // NOTE(bill): Don't err here } - GB_ASSERT(decl->defer_use_checked == false); + GB_ASSERT(decl->proc_checked_state != ProcCheckedState_Checked); + if (decl->defer_use_checked) { + GB_ASSERT(is_type_polymorphic(type, true)); + error(token, "Defer Use Checked: %.*s", LIT(decl->entity->token.string)); + GB_ASSERT(decl->defer_use_checked == false); + } check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls); @@ -1575,10 +1580,8 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de if (decl->parent != nullptr) { Scope *ps = decl->parent->scope; if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) { - return; - } else { - mutex_lock(&ctx->info->deps_mutex); - + return true; + } else MUTEX_GUARD_BLOCK(&ctx->info->deps_mutex) { // NOTE(bill): Add the dependencies from the procedure literal (lambda) // But only at the procedure level for (auto const &entry : decl->deps) { @@ -1589,8 +1592,8 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de Type *t = entry.ptr; ptr_set_add(&decl->parent->type_info_deps, t); } - - mutex_unlock(&ctx->info->deps_mutex); } } + + return true; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index eb9f76547..5445e73c7 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -86,7 +86,6 @@ gb_internal Entity * find_polymorphic_record_entity (CheckerContext *c, Type *or gb_internal void check_not_tuple (CheckerContext *c, Operand *operand); gb_internal void convert_to_typed (CheckerContext *c, Operand *operand, Type *target_type); gb_internal gbString expr_to_string (Ast *expression); -gb_internal void check_proc_body (CheckerContext *c, Token token, DeclInfo *decl, Type *type, Ast *body); gb_internal void update_untyped_expr_type (CheckerContext *c, Ast *e, Type *type, bool final); gb_internal bool check_is_terminating (Ast *node, String const &label); gb_internal bool check_has_break (Ast *stmt, String const &label, bool implicit); @@ -478,6 +477,22 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E if (poly_proc_data) { poly_proc_data->gen_entity = other; } + + DeclInfo *decl = other->decl_info; + if (decl->proc_checked_state != ProcCheckedState_Checked) { + ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); + proc_info->file = other->file; + proc_info->token = other->token; + proc_info->decl = decl; + proc_info->type = other->type; + proc_info->body = decl->proc_lit->ProcLit.body; + proc_info->tags = other->Procedure.tags;; + proc_info->generated_from_polymorphic = true; + proc_info->poly_def_node = poly_def_node; + + check_procedure_later(nctx.checker, proc_info); + } + return true; } } @@ -518,7 +533,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E d->gen_proc_type = final_proc_type; d->type_expr = pl->type; d->proc_lit = proc_lit; - d->proc_checked = false; + d->proc_checked_state = ProcCheckedState_Unchecked; + d->defer_use_checked = false; Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); entity->identifier = ident; @@ -528,7 +544,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E entity->scope = scope->parent; entity->file = base_entity->file; entity->pkg = base_entity->pkg; - entity->flags &= ~EntityFlag_ProcBodyChecked; + entity->flags = 0; + d->entity = entity; AstFile *file = nullptr; { diff --git a/src/checker.cpp b/src/checker.cpp index d3a9c3d2c..f4c9b6822 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,3 +1,5 @@ +#define DEBUG_CHECK_ALL_PROCEDURES 1 + #include "entity.cpp" #include "types.cpp" @@ -179,6 +181,7 @@ gb_internal void import_graph_node_swap(ImportGraphNode **data, isize i, isize j gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { + gb_zero_item(d); d->parent = parent; d->scope = scope; ptr_set_init(&d->deps, heap_allocator()); @@ -438,9 +441,44 @@ gb_internal Entity *scope_lookup(Scope *s, String const &name) { return entity; } +gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, String const &name, Entity *entity) { + if (name == "") { + return nullptr; + } + StringHashKey key = string_hash_string(name); + Entity **found = nullptr; + Entity *result = nullptr; + + found = string_map_get(&s->elements, key); + + if (found) { + if (entity != *found) { + result = *found; + } + goto end; + } + if (s->parent != nullptr && (s->parent->flags & ScopeFlag_Proc) != 0) { + found = string_map_get(&s->parent->elements, key); + if (found) { + if ((*found)->flags & EntityFlag_Result) { + if (entity != *found) { + result = *found; + } + goto end; + } + } + } + + string_map_set(&s->elements, key, entity); + if (entity->scope == nullptr) { + entity->scope = s; + } +end:; + return result; +} -gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity, bool use_mutex=true) { +gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity) { if (name == "") { return nullptr; } @@ -448,9 +486,8 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity Entity **found = nullptr; Entity *result = nullptr; - if (use_mutex) mutex_lock(&s->mutex); - defer (if (use_mutex) mutex_unlock(&s->mutex)); - + MUTEX_GUARD(&s->mutex); + found = string_map_get(&s->elements, key); if (found) { @@ -479,9 +516,14 @@ end:; return result; } -gb_internal Entity *scope_insert(Scope *s, Entity *entity, bool use_mutex) { +gb_internal Entity *scope_insert(Scope *s, Entity *entity) { String name = entity->token.string; - return scope_insert_with_name(s, name, entity, use_mutex); + return scope_insert_with_name(s, name, entity); +} + +gb_internal Entity *scope_insert_no_mutex(Scope *s, Entity *entity) { + String name = entity->token.string; + return scope_insert_with_name_no_mutex(s, name, entity); } @@ -1135,6 +1177,9 @@ gb_internal void init_checker_info(CheckerInfo *i) { map_init(&i->objc_msgSend_types, a); string_map_init(&i->load_file_cache, a); + + array_init(&i->all_procedures, heap_allocator()); + } gb_internal void destroy_checker_info(CheckerInfo *i) { @@ -1934,6 +1979,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { gb_global std::atomic global_procedure_body_in_worker_queue = false; +gb_global std::atomic global_after_checking_procedure_bodies = false; gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc); @@ -1941,12 +1987,24 @@ gb_internal void check_procedure_later(Checker *c, ProcInfo *info) { GB_ASSERT(info != nullptr); GB_ASSERT(info->decl != nullptr); - if (global_procedure_body_in_worker_queue) { + if (global_after_checking_procedure_bodies) { + Entity *e = info->decl->entity; + debugf("CHECK PROCEDURE LATER! %.*s :: %s {...}\n", LIT(e->token.string), type_to_string(e->type)); + } + + if (global_procedure_body_in_worker_queue.load()) { thread_pool_add_task(check_proc_info_worker_proc, info); } else { - GB_ASSERT(global_procedure_body_in_worker_queue == false); array_add(&c->procs_to_check, info); } + + if (DEBUG_CHECK_ALL_PROCEDURES) { + MUTEX_GUARD_BLOCK(&c->info.all_procedures_mutex) { + GB_ASSERT(info != nullptr); + GB_ASSERT(info->decl != nullptr); + array_add(&c->info.all_procedures, info); + } + } } gb_internal void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) { @@ -5010,24 +5068,26 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u if (pi->type == nullptr) { return false; } - Entity *e = pi->decl->entity; - MUTEX_GUARD_BLOCK(&pi->decl->proc_checked_mutex) { - if (pi->decl->proc_checked) { - if (e != nullptr) { - GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); - } - return true; - } - if (e != nullptr && (e->flags & EntityFlag_ProcBodyChecked) != 0) { - GB_ASSERT(pi->decl->proc_checked); - return true; + MUTEX_GUARD(&pi->decl->proc_checked_mutex); + + Entity *e = pi->decl->entity; + switch (pi->decl->proc_checked_state.load()) { + case ProcCheckedState_InProgress: + if (e) { + GB_ASSERT(global_procedure_body_in_worker_queue.load()); } - pi->decl->proc_checked = true; + return false; + case ProcCheckedState_Checked: if (e != nullptr) { - e->flags |= EntityFlag_ProcBodyChecked; + GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); } + return true; + case ProcCheckedState_Unchecked: + // okay + break; } + pi->decl->proc_checked_state.store(ProcCheckedState_InProgress); GB_ASSERT(pi->type->kind == Type_Proc); TypeProc *pt = &pi->type->Proc; @@ -5039,17 +5099,21 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u token = ast_token(pi->poly_def_node); } error(token, "Unspecialized polymorphic procedure '%.*s'", LIT(name)); + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); return false; } if (pt->is_polymorphic && pt->is_poly_specialized) { + Entity *e = pi->decl->entity; + GB_ASSERT(e != nullptr); if ((e->flags & EntityFlag_Used) == 0) { // NOTE(bill, 2019-08-31): It was never used, don't check + // NOTE(bill, 2023-01-02): This may need to be checked again if it is used elsewhere? + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); return false; } } - CheckerContext ctx = make_checker_context(c); defer (destroy_checker_context(&ctx)); reset_checker_context(&ctx, pi->file, untyped); @@ -5077,14 +5141,34 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u ctx.state_flags &= ~StateFlag_type_assert; } - check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); + bool body_was_checked = check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); + + if (body_was_checked) { + pi->decl->proc_checked_state.store(ProcCheckedState_Checked); + if (pi->body) { + Entity *e = pi->decl->entity; + if (e != nullptr) { + e->flags |= EntityFlag_ProcBodyChecked; + } + } + } else { + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); + if (pi->body) { + Entity *e = pi->decl->entity; + if (e != nullptr) { + e->flags &= ~EntityFlag_ProcBodyChecked; + } + } + } + add_untyped_expressions(&c->info, ctx.untyped); + return true; } GB_STATIC_ASSERT(sizeof(isize) == sizeof(void *)); -gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped); +gb_internal bool consume_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped); gb_internal void check_unchecked_bodies(Checker *c) { // NOTE(2021-02-26, bill): Sanity checker @@ -5092,10 +5176,15 @@ gb_internal void check_unchecked_bodies(Checker *c) { // even ones which should not exist, due to the multithreaded nature of the parser // HACK TODO(2021-02-26, bill): Actually fix this race condition + GB_ASSERT(c->procs_to_check.count == 0); + UntypedExprInfoMap untyped = {}; map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); + // use the `procs_to_check` array + global_procedure_body_in_worker_queue = false; + for (auto const &entry : c->info.minimum_dependency_set) { Entity *e = entry.ptr; if (e == nullptr || e->kind != Entity_Procedure) { @@ -5122,19 +5211,22 @@ gb_internal void check_unchecked_bodies(Checker *c) { } debugf("unchecked: %.*s\n", LIT(e->token.string)); - array_add(&c->procs_to_check, pi); + check_procedure_later(c, pi); } } - for (ProcInfo *pi : c->procs_to_check) { - Entity *e = pi->decl->entity; - if (consume_proc_info_queue(c, pi, &untyped)) { - add_dependency_to_set(c, e); - GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); + if (!global_procedure_body_in_worker_queue) { + for_array(i, c->procs_to_check) { + ProcInfo *pi = c->procs_to_check[i]; + consume_proc_info(c, pi, &untyped); } + array_clear(&c->procs_to_check); + } else { + thread_pool_wait(); } - thread_pool_wait(); + global_procedure_body_in_worker_queue = false; + global_after_checking_procedure_bodies = true; } gb_internal void check_test_procedures(Checker *c) { @@ -5172,8 +5264,15 @@ gb_internal void check_test_procedures(Checker *c) { gb_global std::atomic total_bodies_checked; -gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) { +gb_internal bool consume_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) { GB_ASSERT(pi->decl != nullptr); + switch (pi->decl->proc_checked_state.load()) { + case ProcCheckedState_InProgress: + return false; + case ProcCheckedState_Checked: + return true; + } + if (pi->decl->parent && pi->decl->parent->entity) { Entity *parent = pi->decl->parent->entity; // NOTE(bill): Only check a nested procedure if its parent's body has been checked first @@ -5187,9 +5286,11 @@ gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprIn if (untyped) { map_clear(untyped); } - bool ok = check_proc_info(c, pi, untyped); - total_bodies_checked.fetch_add(1, std::memory_order_relaxed); - return ok; + if (check_proc_info(c, pi, untyped)) { + total_bodies_checked.fetch_add(1, std::memory_order_relaxed); + return true; + } + return false; } struct CheckProcedureBodyWorkerData { @@ -5218,9 +5319,11 @@ gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) { } } map_clear(untyped); - bool ok = check_proc_info(c, pi, untyped); - total_bodies_checked.fetch_add(1, std::memory_order_relaxed); - return !ok; + if (check_proc_info(c, pi, untyped)) { + total_bodies_checked.fetch_add(1, std::memory_order_relaxed); + return 0; + } + return 1; } @@ -5247,7 +5350,7 @@ gb_internal void check_procedure_bodies(Checker *c) { if (thread_count == 1) { UntypedExprInfoMap *untyped = &check_procedure_bodies_worker_data[0].untyped; for_array(i, c->procs_to_check) { - consume_proc_info_queue(c, c->procs_to_check[i], untyped); + consume_proc_info(c, c->procs_to_check[i], untyped); } array_clear(&c->procs_to_check); @@ -5266,9 +5369,6 @@ gb_internal void check_procedure_bodies(Checker *c) { thread_pool_wait(); - debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); - - global_procedure_body_in_worker_queue = false; } gb_internal void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) { @@ -5662,9 +5762,6 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("check test procedures"); check_test_procedures(c); - TIME_SECTION("check bodies have all been checked"); - check_unchecked_bodies(c); - TIME_SECTION("add type info for type definitions"); add_type_info_for_type_definitions(c); check_merge_queues_into_arrays(c); @@ -5672,6 +5769,12 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("generate minimum dependency set"); generate_minimum_dependency_set(c, c->info.entry_point); + TIME_SECTION("check bodies have all been checked"); + check_unchecked_bodies(c); + + check_merge_queues_into_arrays(c); + + TIME_SECTION("check entry point"); if (build_context.build_mode == BuildMode_Executable && !build_context.no_entry_point && build_context.command_kind != Command_test) { Scope *s = c->info.init_scope; @@ -5694,11 +5797,39 @@ gb_internal void check_parsed_files(Checker *c) { } } + thread_pool_wait(); + GB_ASSERT(c->procs_to_check.count == 0); + + if (DEBUG_CHECK_ALL_PROCEDURES) { + UntypedExprInfoMap untyped = {}; + map_init(&untyped, heap_allocator()); + defer (map_destroy(&untyped)); + + for_array(i, c->info.all_procedures) { + ProcInfo *pi = c->info.all_procedures[i]; + GB_ASSERT(pi != nullptr); + GB_ASSERT(pi->decl != nullptr); + Entity *e = pi->decl->entity; + auto proc_checked_state = pi->decl->proc_checked_state.load(); + if (e && ((e->flags & EntityFlag_ProcBodyChecked) == 0)) { + if ((e->flags & EntityFlag_Used) != 0) { + debugf("%.*s :: %s\n", LIT(e->token.string), type_to_string(e->type)); + debugf("proc body unchecked\n"); + debugf("Checked State: %s\n\n", ProcCheckedState_strings[proc_checked_state]); + + consume_proc_info(c, pi, &untyped); + } + } + } + } + + debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); + TIME_SECTION("check unique package names"); check_unique_package_names(c); - TIME_SECTION("sanity checks"); + check_merge_queues_into_arrays(c); GB_ASSERT(c->info.entity_queue.count.load(std::memory_order_relaxed) == 0); GB_ASSERT(c->info.definition_queue.count.load(std::memory_order_relaxed) == 0); @@ -5717,5 +5848,6 @@ gb_internal void check_parsed_files(Checker *c) { } } + TIME_SECTION("type check finish"); } diff --git a/src/checker.hpp b/src/checker.hpp index eaad1fa63..37aff41b1 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -142,6 +142,20 @@ typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc); gb_internal void check_decl_attributes(CheckerContext *c, Array const &attributes, DeclAttributeProc *proc, AttributeContext *ac); +enum ProcCheckedState : u8 { + ProcCheckedState_Unchecked, + ProcCheckedState_InProgress, + ProcCheckedState_Checked, + + ProcCheckedState_COUNT +}; + +char const *ProcCheckedState_strings[ProcCheckedState_COUNT] { + "Unchecked", + "In Progress", + "Checked", +}; + // DeclInfo is used to store information of certain declarations to allow for "any order" usage struct DeclInfo { DeclInfo * parent; // NOTE(bill): only used for procedure literals at the moment @@ -157,7 +171,7 @@ struct DeclInfo { Type * gen_proc_type; // Precalculated bool is_using; bool where_clauses_evaluated; - bool proc_checked; + std::atomic proc_checked_state; BlockingMutex proc_checked_mutex; isize defer_used; bool defer_use_checked; @@ -375,6 +389,9 @@ struct CheckerInfo { BlockingMutex load_file_mutex; StringMap load_file_cache; + + BlockingMutex all_procedures_mutex;; + Array all_procedures; }; struct CheckerContext { @@ -458,7 +475,7 @@ gb_internal Entity *entity_of_node(Ast *expr); gb_internal Entity *scope_lookup_current(Scope *s, String const &name); gb_internal Entity *scope_lookup (Scope *s, String const &name); gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_); -gb_internal Entity *scope_insert (Scope *s, Entity *entity, bool use_mutex=true); +gb_internal Entity *scope_insert (Scope *s, Entity *entity); gb_internal void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 1c401552e..3e62f678a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2255,6 +2255,12 @@ gb_internal void lb_generate_code(lbGenerator *gen) { } } + if (build_context.ignore_llvm_build) { + gb_printf_err("LLVM SUCCESS!\n"); + gb_exit(1); + return; + } + if (do_threading && non_empty_module_count > 1) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 9f7caa3bb..50fb5701f 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -301,6 +301,7 @@ struct lbProcedure { lbBlock * curr_block; lbTargetList * target_list; PtrMap direct_parameters; + PtrMap local_entity_map; Ast *curr_stmt; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index d574caf4c..28a68b065 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3404,7 +3404,11 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp lbValue v = {}; - lbValue *found = map_get(&p->module->values, e); + lbValue *found = nullptr; + found = map_get(&p->local_entity_map, e); + if (found == nullptr) { + found = map_get(&p->module->values, e); + } if (found) { v = *found; } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 0508c6171..940c94a13 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2714,7 +2714,6 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { return g; } } - GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); return {}; } @@ -2845,6 +2844,10 @@ gb_internal lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero lb_mem_zero_ptr(p, ptr, type, alignment); } + if (e != nullptr) { + map_set(&p->local_entity_map, e, val); + } + return lb_addr(val); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 384d29ca7..9691afebc 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -68,7 +68,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); if (!entity->Procedure.is_foreign) { - GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s", LIT(entity->token.string), type_to_string(entity->type)); + GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s (was parapoly: %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true)); } String link_name = {}; @@ -487,6 +487,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { lb_start_block(p, p->entry_block); map_init(&p->direct_parameters, heap_allocator()); + map_init(&p->local_entity_map, heap_allocator()); GB_ASSERT(p->type != nullptr); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 6400a8a9d..cdfb28aa7 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1531,6 +1531,9 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { lbValue global_val = {global, alloc_type_pointer(e->type)}; lb_add_entity(p->module, e, global_val); lb_add_member(p->module, mangled_name, global_val); + if (e) { + map_set(&p->local_entity_map, e, global_val); + } } } gb_internal void lb_append_tuple_values(lbProcedure *p, Array *dst_values, lbValue src_value) { @@ -2188,9 +2191,10 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { for_array(i, vd->names) { Ast *name = vd->names[i]; if (!is_blank_ident(name)) { + GB_ASSERT(name->kind == Ast_Ident); Entity *e = entity_of_node(name); TokenPos pos = ast_token(name).pos; - GB_ASSERT_MSG(e != nullptr, "%s", token_pos_to_string(pos)); + GB_ASSERT_MSG(e != nullptr, "\n%s missing entity for %.*s", token_pos_to_string(pos), LIT(name->Ident.token.string)); if (e->flags & EntityFlag_Static) { // NOTE(bill): If one of the entities is static, they all are is_static = true; diff --git a/src/main.cpp b/src/main.cpp index 3ad0e160f..42d6f8e87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -660,6 +660,7 @@ enum BuildFlagKind { // internal use only BuildFlag_InternalIgnoreLazy, + BuildFlag_InternalIgnoreLLVMBuild, #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, @@ -832,6 +833,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); @@ -1491,6 +1493,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalIgnoreLazy: build_context.ignore_lazy = true; break; + case BuildFlag_InternalIgnoreLLVMBuild: + build_context.ignore_llvm_build = true; + break; #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From c293f5b7ebc3b733e996a97c6e32d678f13b3ee5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 16:56:05 +0000 Subject: Remove unneeded mutex --- src/check_expr.cpp | 33 +++++++++++++++++---------------- src/checker.hpp | 7 ++++++- src/common_memory.cpp | 18 ++++++------------ src/llvm_backend_stmt.cpp | 5 ++--- src/main.cpp | 3 +-- src/threading.cpp | 17 +++++++++-------- 6 files changed, 41 insertions(+), 42 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 5445e73c7..f47361c27 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -193,8 +193,7 @@ gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, b GB_ASSERT(e->kind == Entity_TypeName); GB_ASSERT(e->TypeName.objc_metadata != nullptr); auto *objc_metadata = e->TypeName.objc_metadata; - mutex_lock(objc_metadata->mutex); - defer (mutex_unlock(objc_metadata->mutex)); + MUTEX_GUARD(objc_metadata->mutex); StringSet set = {}; string_set_init(&set, heap_allocator()); @@ -369,8 +368,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E GB_ASSERT(dst == nullptr); } - mutex_lock(&info->gen_procs_mutex); - defer (mutex_unlock(&info->gen_procs_mutex)); + // MUTEX_GUARD(&info->gen_procs_mutex); if (!src->Proc.is_polymorphic || src->Proc.is_poly_specialized) { return false; @@ -436,11 +434,14 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return false; } - auto *found_gen_procs = map_get(&info->gen_procs, base_entity->identifier.load()); + GenProcsData *found_gen_procs = nullptr; + + MUTEX_GUARD(&info->gen_procs_mutex); + + found_gen_procs = map_get(&info->gen_procs, base_entity->identifier.load()); if (found_gen_procs) { - auto procs = *found_gen_procs; - for_array(i, procs) { - Entity *other = procs[i]; + MUTEX_GUARD(&found_gen_procs->mutex); + for (Entity *other : found_gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { if (poly_proc_data) { @@ -463,15 +464,13 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E // LEAK TODO(bill): Cloning this AST may be leaky Ast *cloned_proc_type_node = clone_ast(pt->node); success = check_procedure_type(&nctx, final_proc_type, cloned_proc_type_node, &operands); - if (!success) { return false; } if (found_gen_procs) { - auto procs = *found_gen_procs; - for_array(i, procs) { - Entity *other = procs[i]; + MUTEX_GUARD(&found_gen_procs->mutex); + for (Entity *other : found_gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { if (poly_proc_data) { @@ -567,11 +566,13 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E proc_info->poly_def_node = poly_def_node; if (found_gen_procs) { - array_add(found_gen_procs, entity); + MUTEX_GUARD(&found_gen_procs->mutex); + array_add(&found_gen_procs->procs, entity); } else { - auto array = array_make(heap_allocator()); - array_add(&array, entity); - map_set(&info->gen_procs, base_entity->identifier.load(), array); + GenProcsData gen_proc_data = {}; + gen_proc_data.procs = array_make(heap_allocator()); + array_add(&gen_proc_data.procs, entity); + map_set(&info->gen_procs, base_entity->identifier.load(), gen_proc_data); } if (poly_proc_data) { diff --git a/src/checker.hpp b/src/checker.hpp index 37aff41b1..56f8707d3 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -311,6 +311,11 @@ struct LoadFileCache { StringMap hashes; }; +struct GenProcsData { + Array procs; + BlockingMutex mutex; +}; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Checker *checker; @@ -360,7 +365,7 @@ struct CheckerInfo { RecursiveMutex gen_procs_mutex; RecursiveMutex gen_types_mutex; - PtrMap > gen_procs; // Key: Ast * | Identifier -> Entity + PtrMap gen_procs; // Key: Ast * | Identifier -> Entity PtrMap > gen_types; BlockingMutex type_info_mutex; // NOT recursive diff --git a/src/common_memory.cpp b/src/common_memory.cpp index 2022554cf..cdf2281fe 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -37,7 +37,6 @@ gb_internal gb_inline void *align_formula_ptr(void *ptr, isize align) { gb_global BlockingMutex global_memory_block_mutex; -gb_global BlockingMutex global_memory_allocator_mutex; gb_internal void platform_virtual_memory_init(void); @@ -55,9 +54,9 @@ struct MemoryBlock { }; struct Arena { - MemoryBlock *curr_block; - isize minimum_block_size; - bool ignore_mutex; + MemoryBlock * curr_block; + isize minimum_block_size; + BlockingMutex mutex; }; enum { DEFAULT_MINIMUM_BLOCK_SIZE = 8ll*1024ll*1024ll }; @@ -83,10 +82,7 @@ gb_internal isize arena_align_forward_offset(Arena *arena, isize alignment) { gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { GB_ASSERT(gb_is_power_of_two(alignment)); - BlockingMutex *mutex = &global_memory_allocator_mutex; - if (!arena->ignore_mutex) { - mutex_lock(mutex); - } + mutex_lock(&arena->mutex); isize size = 0; if (arena->curr_block != nullptr) { @@ -113,9 +109,7 @@ gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { curr_block->used += size; GB_ASSERT(curr_block->used <= curr_block->size); - if (!arena->ignore_mutex) { - mutex_unlock(mutex); - } + mutex_unlock(&arena->mutex); // NOTE(bill): memory will be zeroed by default due to virtual memory return ptr; @@ -304,7 +298,7 @@ gb_internal GB_ALLOCATOR_PROC(arena_allocator_proc) { } -gb_global gb_thread_local Arena permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE, true}; +gb_global gb_thread_local Arena permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; gb_internal gbAllocator permanent_allocator() { return arena_allocator(&permanent_arena); } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 06abebc78..8742423a5 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -57,9 +57,8 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) if (pl->body != nullptr) { auto *found = map_get(&info->gen_procs, ident); if (found) { - auto procs = *found; - for_array(i, procs) { - Entity *e = procs[i]; + MUTEX_GUARD(&found->mutex); + for (Entity *e : found->procs) { if (!ptr_set_exists(min_dep_set, e)) { continue; } diff --git a/src/main.cpp b/src/main.cpp index 42d6f8e87..ad9d6b0ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,8 +17,7 @@ gb_global ThreadPool global_thread_pool; gb_internal void init_global_thread_pool(void) { isize thread_count = gb_max(build_context.thread_count, 1); - isize worker_count = thread_count-1; // NOTE(bill): The main thread will also be used for work - thread_pool_init(&global_thread_pool, permanent_allocator(), worker_count, "ThreadPoolWorker"); + thread_pool_init(&global_thread_pool, permanent_allocator(), thread_count, "ThreadPoolWorker"); } gb_internal bool thread_pool_add_task(WorkerTaskProc *proc, void *data) { return thread_pool_add_task(&global_thread_pool, proc, data); diff --git a/src/threading.cpp b/src/threading.cpp index 4c7aa8f92..c5db5d1b4 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -77,22 +77,23 @@ gb_internal void yield_process(void); struct MutexGuard { - MutexGuard() = delete; + MutexGuard() = delete; MutexGuard(MutexGuard const &) = delete; + MutexGuard(MutexGuard &&) = delete; - MutexGuard(BlockingMutex *bm) : bm{bm} { + explicit MutexGuard(BlockingMutex *bm) noexcept : bm{bm} { mutex_lock(this->bm); } - MutexGuard(RecursiveMutex *rm) : rm{rm} { + explicit MutexGuard(RecursiveMutex *rm) noexcept : rm{rm} { mutex_lock(this->rm); } - MutexGuard(BlockingMutex &bm) : bm{&bm} { + explicit MutexGuard(BlockingMutex &bm) noexcept : bm{&bm} { mutex_lock(this->bm); } - MutexGuard(RecursiveMutex &rm) : rm{&rm} { + explicit MutexGuard(RecursiveMutex &rm) noexcept : rm{&rm} { mutex_lock(this->rm); } - ~MutexGuard() { + ~MutexGuard() noexcept { if (this->bm) { mutex_unlock(this->bm); } else if (this->rm) { @@ -100,14 +101,14 @@ struct MutexGuard { } } - operator bool() const { return true; } + operator bool() const noexcept { return true; } BlockingMutex *bm; RecursiveMutex *rm; }; #define MUTEX_GUARD_BLOCK(m) if (MutexGuard GB_DEFER_3(_mutex_guard_){m}) -#define MUTEX_GUARD(m) MutexGuard GB_DEFER_3(_mutex_guard_){m} +#define MUTEX_GUARD(m) mutex_lock(m); defer (mutex_unlock(m)) struct RecursiveMutex { -- cgit v1.2.3 From 6bd3a9d422d0567ead89e2465f46068d52f34f20 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 22:23:49 +0000 Subject: Be very explicit where the gen_procs_mutex can be unlock --- src/check_expr.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index f47361c27..b40c48459 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -436,14 +436,19 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E GenProcsData *found_gen_procs = nullptr; - MUTEX_GUARD(&info->gen_procs_mutex); + // @@GPM + mutex_lock(&info->gen_procs_mutex); found_gen_procs = map_get(&info->gen_procs, base_entity->identifier.load()); + if (found_gen_procs) { MUTEX_GUARD(&found_gen_procs->mutex); for (Entity *other : found_gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { + // @@GPM + mutex_unlock(&info->gen_procs_mutex); + if (poly_proc_data) { poly_proc_data->gen_entity = other; } @@ -465,6 +470,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E Ast *cloned_proc_type_node = clone_ast(pt->node); success = check_procedure_type(&nctx, final_proc_type, cloned_proc_type_node, &operands); if (!success) { + // @@GPM + mutex_unlock(&info->gen_procs_mutex); return false; } @@ -473,6 +480,9 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E for (Entity *other : found_gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { + // @@GPM + mutex_unlock(&info->gen_procs_mutex); + if (poly_proc_data) { poly_proc_data->gen_entity = other; } @@ -498,6 +508,11 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } } + if (found_gen_procs) { + // @@GPM + mutex_unlock(&info->gen_procs_mutex); + } + Ast *proc_lit = clone_ast(old_decl->proc_lit); ast_node(pl, ProcLit, proc_lit); @@ -555,6 +570,19 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } } + if (found_gen_procs) { + MUTEX_GUARD(&found_gen_procs->mutex); + array_add(&found_gen_procs->procs, entity); + } else { + GenProcsData gen_proc_data = {}; + gen_proc_data.procs = array_make(heap_allocator()); + array_add(&gen_proc_data.procs, entity); + map_set(&info->gen_procs, base_entity->identifier.load(), gen_proc_data); + + // @@GPM + mutex_unlock(&info->gen_procs_mutex); + } + ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); proc_info->file = file; proc_info->token = token; @@ -565,15 +593,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E proc_info->generated_from_polymorphic = true; proc_info->poly_def_node = poly_def_node; - if (found_gen_procs) { - MUTEX_GUARD(&found_gen_procs->mutex); - array_add(&found_gen_procs->procs, entity); - } else { - GenProcsData gen_proc_data = {}; - gen_proc_data.procs = array_make(heap_allocator()); - array_add(&gen_proc_data.procs, entity); - map_set(&info->gen_procs, base_entity->identifier.load(), gen_proc_data); - } if (poly_proc_data) { poly_proc_data->gen_entity = entity; -- cgit v1.2.3 From 69b075782bac981ceeea5eea8f544e346f0fe6b5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 22:40:28 +0000 Subject: Use a package local mutex for `add_type_and_value` --- src/check_decl.cpp | 9 ++++++--- src/check_expr.cpp | 56 +++++++++++++++++++++++++++--------------------------- src/check_type.cpp | 2 +- src/checker.cpp | 13 +++++++++---- src/checker.hpp | 2 +- src/parser.hpp | 1 + 6 files changed, 46 insertions(+), 37 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 2b6868f05..e3486924c 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -45,7 +45,7 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o if (operand->mode == Addressing_Type) { if (e->type != nullptr && is_type_typeid(e->type)) { add_type_info_type(ctx, operand->type); - add_type_and_value(ctx->info, operand->expr, Addressing_Value, e->type, exact_value_typeid(operand->type)); + add_type_and_value(ctx, operand->expr, Addressing_Value, e->type, exact_value_typeid(operand->type)); return e->type; } else { gbString t = type_to_string(operand->type); @@ -1585,13 +1585,16 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de // NOTE(bill): Add the dependencies from the procedure literal (lambda) // But only at the procedure level - MUTEX_GUARD_BLOCK(decl->deps_mutex) MUTEX_GUARD_BLOCK(decl->parent->deps_mutex) { + MUTEX_GUARD_BLOCK(decl->deps_mutex) + MUTEX_GUARD_BLOCK(decl->parent->deps_mutex) { for (auto const &entry : decl->deps) { Entity *e = entry.ptr; ptr_set_add(&decl->parent->deps, e); } } - MUTEX_GUARD_BLOCK(decl->type_info_deps_mutex) MUTEX_GUARD_BLOCK(decl->parent->type_info_deps_mutex) { + + MUTEX_GUARD_BLOCK(decl->type_info_deps_mutex) + MUTEX_GUARD_BLOCK(decl->parent->type_info_deps_mutex) { for (auto const &entry : decl->type_info_deps) { Type *t = entry.ptr; ptr_set_add(&decl->parent->type_info_deps, t); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b40c48459..9feac93ea 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -852,7 +852,7 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand PolyProcData poly_proc_data = {}; if (check_polymorphic_procedure_assignment(c, operand, type, operand->expr, &poly_proc_data)) { Entity *e = poly_proc_data.gen_entity; - add_type_and_value(c->info, operand->expr, Addressing_Value, e->type, {}); + add_type_and_value(c, operand->expr, Addressing_Value, e->type, {}); add_entity_use(c, operand->expr, e); return 4; } @@ -1082,7 +1082,7 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ if (check_is_assignable_to(c, operand, type)) { if (operand->mode == Addressing_Type && is_type_typeid(type)) { add_type_info_type(c, operand->type); - add_type_and_value(c->info, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type)); + add_type_and_value(c, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type)); } } else { gbString expr_str = expr_to_string(operand->expr); @@ -2374,7 +2374,7 @@ gb_internal void check_comparison(CheckerContext *c, Operand *x, Operand *y, Tok if (x->mode == Addressing_Type && is_type_typeid(y->type)) { add_type_info_type(c, x->type); add_type_info_type(c, y->type); - add_type_and_value(c->info, x->expr, Addressing_Value, y->type, exact_value_typeid(x->type)); + add_type_and_value(c, x->expr, Addressing_Value, y->type, exact_value_typeid(x->type)); x->mode = Addressing_Value; x->type = t_untyped_bool; @@ -2382,7 +2382,7 @@ gb_internal void check_comparison(CheckerContext *c, Operand *x, Operand *y, Tok } else if (is_type_typeid(x->type) && y->mode == Addressing_Type) { add_type_info_type(c, x->type); add_type_info_type(c, y->type); - add_type_and_value(c->info, y->expr, Addressing_Value, x->type, exact_value_typeid(y->type)); + add_type_and_value(c, y->expr, Addressing_Value, x->type, exact_value_typeid(y->type)); x->mode = Addressing_Value; x->type = t_untyped_bool; @@ -3615,7 +3615,7 @@ gb_internal void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, if (old == nullptr) { if (type != nullptr && type != t_invalid) { if (e->tav.type == nullptr || e->tav.type == t_invalid) { - add_type_and_value(c->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value); + add_type_and_value(c, e, e->tav.mode, type ? type : e->tav.type, e->tav.value); if (e->kind == Ast_TernaryIfExpr) { update_untyped_expr_type(c, e->TernaryIfExpr.x, type, final); update_untyped_expr_type(c, e->TernaryIfExpr.y, type, final); @@ -3721,7 +3721,7 @@ gb_internal void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, return; } - add_type_and_value(c->info, e, old->mode, type, old->value); + add_type_and_value(c, e, old->mode, type, old->value); } gb_internal void update_untyped_expr_value(CheckerContext *c, Ast *e, ExactValue value) { @@ -4569,7 +4569,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod operand->mode = Addressing_ProcGroup; operand->proc_group = entity; - add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return entity; } GB_ASSERT_MSG(entity->type != nullptr, "%.*s (%.*s)", LIT(entity->token.string), LIT(entity_strings[entity->kind])); @@ -4738,7 +4738,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod } Entity *swizzle_entity = alloc_entity_variable(nullptr, make_token_ident(field_name), operand->type, EntityState_Resolved); - add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return swizzle_entity; } end_of_array_selector_swizzle:; @@ -4782,7 +4782,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod operand->value = field_value; operand->type = entity->type; add_entity_use(c, selector, entity); - add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return entity; } @@ -4807,7 +4807,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod operand->value = field_value; operand->type = entity->type; add_entity_use(c, selector, entity); - add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return entity; } @@ -4895,7 +4895,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod break; } - add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return entity; } @@ -5361,7 +5361,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { if (o.mode == Addressing_Type && is_type_typeid(e->type)) { add_type_info_type(c, o.type); - add_type_and_value(c->info, o.expr, Addressing_Value, e->type, exact_value_typeid(o.type)); + add_type_and_value(c, o.expr, Addressing_Value, e->type, exact_value_typeid(o.type)); } else if (show_error && is_type_untyped(o.type)) { update_untyped_expr_type(c, o.expr, t, true); } @@ -5412,7 +5412,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } if (o.mode == Addressing_Type && is_type_typeid(t)) { add_type_info_type(c, o.type); - add_type_and_value(c->info, o.expr, Addressing_Value, t, exact_value_typeid(o.type)); + add_type_and_value(c, o.expr, Addressing_Value, t, exact_value_typeid(o.type)); } else if (show_error && is_type_untyped(o.type)) { update_untyped_expr_type(c, o.expr, t, true); } @@ -5425,7 +5425,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { data->score = score; data->result_type = final_proc_type->Proc.results; data->gen_entity = gen_entity; - add_type_and_value(c->info, ce->proc, Addressing_Value, final_proc_type, {}); + add_type_and_value(c, ce->proc, Addressing_Value, final_proc_type, {}); } return err; @@ -5625,7 +5625,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_named_call_arguments) { if (o->mode == Addressing_Type && is_type_typeid(e->type)) { add_type_info_type(c, o->type); - add_type_and_value(c->info, o->expr, Addressing_Value, e->type, exact_value_typeid(o->type)); + add_type_and_value(c, o->expr, Addressing_Value, e->type, exact_value_typeid(o->type)); } } @@ -5633,7 +5633,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_named_call_arguments) { data->score = score; data->result_type = pt->results; data->gen_entity = gen_entity; - add_type_and_value(c->info, ce->proc, Addressing_Value, proc_type, {}); + add_type_and_value(c, ce->proc, Addressing_Value, proc_type, {}); } return err; @@ -6635,7 +6635,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c operand->builtin_id = BuiltinProc_DIRECTIVE; operand->expr = proc; operand->type = t_invalid; - add_type_and_value(c->info, proc, operand->mode, operand->type, operand->value); + add_type_and_value(c, proc, operand->mode, operand->type, operand->value); } else { error(proc, "Unknown directive: #%.*s", LIT(name)); operand->expr = proc; @@ -6713,7 +6713,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c GB_ASSERT(ot->kind == Type_Named); Entity *e = ot->Named.type_name; add_entity_use(c, ident, e); - add_type_and_value(c->info, call, Addressing_Type, ot, empty_exact_value); + add_type_and_value(c, call, Addressing_Type, ot, empty_exact_value); } else { operand->mode = Addressing_Invalid; operand->type = t_invalid; @@ -6885,7 +6885,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } } - // add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value); + // add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return Expr_Expr; } @@ -7129,8 +7129,8 @@ gb_internal bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand * return false; } - add_type_and_value(c->info, ie->left, x->mode, x->type, x->value); - add_type_and_value(c->info, ie->right, y->mode, y->type, y->value); + add_type_and_value(c, ie->left, x->mode, x->type, x->value); + add_type_and_value(c, ie->right, y->mode, y->type, y->value); return true; } @@ -7146,7 +7146,7 @@ gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Opera return true; } if (expr->kind == Ast_ProcLit) { - add_type_and_value(c->info, expr, Addressing_Constant, type_of_expr(expr), exact_value_procedure(expr)); + add_type_and_value(c, expr, Addressing_Constant, type_of_expr(expr), exact_value_procedure(expr)); return true; } } @@ -7255,7 +7255,7 @@ gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type * Type *pt = base_type(type_of_expr(expr->CallExpr.proc)); if (is_type_proc(pt)) { Type *tuple = pt->Proc.results; - add_type_and_value(c->info, x->expr, x->mode, tuple, x->value); + add_type_and_value(c, x->expr, x->mode, tuple, x->value); if (pt->Proc.result_count >= 2) { if (ok_type_) *ok_type_ = tuple->Tuple.variables[1]->type; @@ -7268,7 +7268,7 @@ gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type * Type *tuple = make_optional_ok_type(x->type); if (ok_type_) *ok_type_ = tuple->Tuple.variables[1]->type; - add_type_and_value(c->info, x->expr, x->mode, tuple, x->value); + add_type_and_value(c, x->expr, x->mode, tuple, x->value); x->type = tuple; GB_ASSERT(is_type_tuple(type_of_expr(x->expr))); } @@ -7688,7 +7688,7 @@ gb_internal ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node Type *left_type = nullptr; Type *right_type = nullptr; check_or_else_split_types(c, &x, name, &left_type, &right_type); - add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value); + add_type_and_value(c, arg, x.mode, x.type, x.value); if (left_type != nullptr) { if (!y_is_diverging) { @@ -7723,7 +7723,7 @@ gb_internal ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *no Type *left_type = nullptr; Type *right_type = nullptr; check_or_return_split_types(c, &x, name, &left_type, &right_type); - add_type_and_value(&c->checker->info, re->expr, x.mode, x.type, x.value); + add_type_and_value(c, re->expr, x.mode, x.type, x.value); if (right_type == nullptr) { check_or_else_expr_no_value_error(c, name, x, type_hint); @@ -8149,7 +8149,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * error(elem, "Expected a constant integer as an array field"); continue; } - // add_type_and_value(c->info, op_index.expr, op_index.mode, op_index.type, op_index.value); + // add_type_and_value(c, op_index.expr, op_index.mode, op_index.type, op_index.value); i64 index = exact_value_to_i64(op_index.value); @@ -9783,7 +9783,7 @@ gb_internal ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, T } check_rtti_type_disallowed(node, o->type, "An expression is using a type, %s, which has been disallowed"); - add_type_and_value(c->info, node, o->mode, o->type, o->value); + add_type_and_value(c, node, o->mode, o->type, o->value); return kind; } diff --git a/src/check_type.cpp b/src/check_type.cpp index 4634e1fbe..05fdbf4d3 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3045,7 +3045,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) #endif if (is_type_typed(type)) { - add_type_and_value(ctx->info, e, Addressing_Type, type, empty_exact_value); + add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value); } else { gbString name = type_to_string(type); error(e, "Invalid type definition of %s", name); diff --git a/src/checker.cpp b/src/checker.cpp index f80ea9e4c..e48142c82 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1440,7 +1440,7 @@ gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, check_set_expr_info(c, expr, mode, type, value); } -gb_internal void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mode, Type *type, ExactValue value) { +gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue value) { if (expr == nullptr) { return; } @@ -1451,7 +1451,12 @@ gb_internal void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mo return; } - mutex_lock(&i->type_and_value_mutex); + BlockingMutex *mutex = &ctx->info->type_and_value_mutex; + if (ctx->pkg) { + mutex = &ctx->pkg->type_and_value_mutex; + } + + mutex_lock(mutex); Ast *prev_expr = nullptr; while (prev_expr != expr) { prev_expr = expr; @@ -1473,7 +1478,7 @@ gb_internal void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mo expr = unparen_expr(expr); } - mutex_unlock(&i->type_and_value_mutex); + mutex_unlock(mutex); } gb_internal void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) { @@ -5701,7 +5706,7 @@ gb_internal void check_parsed_files(Checker *c) { if (is_type_typed(u.info->type)) { compiler_error("%s (type %s) is typed!", expr_to_string(u.expr), type_to_string(u.info->type)); } - add_type_and_value(&c->info, u.expr, u.info->mode, u.info->type, u.info->value); + add_type_and_value(&c->builtin_ctx, u.expr, u.info->mode, u.info->type, u.info->value); } diff --git a/src/checker.hpp b/src/checker.hpp index 62f655f95..04cb1e311 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -482,7 +482,7 @@ gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **s gb_internal Entity *scope_insert (Scope *s, Entity *entity); -gb_internal void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value); +gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue value); gb_internal ExprInfo *check_get_expr_info (CheckerContext *c, Ast *expr); gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue value); gb_internal void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity); diff --git a/src/parser.hpp b/src/parser.hpp index c33739ebe..b492cfa85 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -174,6 +174,7 @@ struct AstPackage { BlockingMutex files_mutex; BlockingMutex foreign_files_mutex; + BlockingMutex type_and_value_mutex; MPMCQueue exported_entity_queue; -- cgit v1.2.3 From 8ece92f1f69217ae5b143cf0e7d812c0f857fa8d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 23:21:16 +0000 Subject: Minimize the parapoly mutex usage a bit --- src/check_expr.cpp | 94 +++++++++++++++++++++-------------------------- src/checker.hpp | 2 +- src/llvm_backend_stmt.cpp | 5 ++- 3 files changed, 46 insertions(+), 55 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9feac93ea..65a411dc1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -434,20 +434,22 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return false; } - GenProcsData *found_gen_procs = nullptr; + GenProcsData *gen_procs = nullptr; - // @@GPM + // @@GPM ////////////////////////// mutex_lock(&info->gen_procs_mutex); + /////////////////////////////////// - found_gen_procs = map_get(&info->gen_procs, base_entity->identifier.load()); - - if (found_gen_procs) { - MUTEX_GUARD(&found_gen_procs->mutex); - for (Entity *other : found_gen_procs->procs) { + auto *found = map_get(&info->gen_procs, base_entity->identifier.load()); + if (found) { + gen_procs = *found; + MUTEX_GUARD(&gen_procs->mutex); + for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { - // @@GPM + // @@GPM //////////////////////////// mutex_unlock(&info->gen_procs_mutex); + ///////////////////////////////////// if (poly_proc_data) { poly_proc_data->gen_entity = other; @@ -455,6 +457,10 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } + } else { + gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); + gen_procs->procs.allocator = heap_allocator(); + map_set(&info->gen_procs, base_entity->identifier.load(), gen_procs); } { @@ -469,50 +475,43 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E // LEAK TODO(bill): Cloning this AST may be leaky Ast *cloned_proc_type_node = clone_ast(pt->node); success = check_procedure_type(&nctx, final_proc_type, cloned_proc_type_node, &operands); + + // @@GPM //////////////////////////// + mutex_unlock(&info->gen_procs_mutex); + ///////////////////////////////////// + if (!success) { - // @@GPM - mutex_unlock(&info->gen_procs_mutex); return false; } - if (found_gen_procs) { - MUTEX_GUARD(&found_gen_procs->mutex); - for (Entity *other : found_gen_procs->procs) { - Type *pt = base_type(other->type); - if (are_types_identical(pt, final_proc_type)) { - // @@GPM - mutex_unlock(&info->gen_procs_mutex); - - if (poly_proc_data) { - poly_proc_data->gen_entity = other; - } + MUTEX_GUARD(&gen_procs->mutex); + for (Entity *other : gen_procs->procs) { + Type *pt = base_type(other->type); + if (are_types_identical(pt, final_proc_type)) { + if (poly_proc_data) { + poly_proc_data->gen_entity = other; + } - DeclInfo *decl = other->decl_info; - if (decl->proc_checked_state != ProcCheckedState_Checked) { - ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); - proc_info->file = other->file; - proc_info->token = other->token; - proc_info->decl = decl; - proc_info->type = other->type; - proc_info->body = decl->proc_lit->ProcLit.body; - proc_info->tags = other->Procedure.tags;; - proc_info->generated_from_polymorphic = true; - proc_info->poly_def_node = poly_def_node; - - check_procedure_later(nctx.checker, proc_info); - } + DeclInfo *decl = other->decl_info; + if (decl->proc_checked_state != ProcCheckedState_Checked) { + ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); + proc_info->file = other->file; + proc_info->token = other->token; + proc_info->decl = decl; + proc_info->type = other->type; + proc_info->body = decl->proc_lit->ProcLit.body; + proc_info->tags = other->Procedure.tags;; + proc_info->generated_from_polymorphic = true; + proc_info->poly_def_node = poly_def_node; - return true; + check_procedure_later(nctx.checker, proc_info); } + + return true; } } } - if (found_gen_procs) { - // @@GPM - mutex_unlock(&info->gen_procs_mutex); - } - Ast *proc_lit = clone_ast(old_decl->proc_lit); ast_node(pl, ProcLit, proc_lit); @@ -570,17 +569,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } } - if (found_gen_procs) { - MUTEX_GUARD(&found_gen_procs->mutex); - array_add(&found_gen_procs->procs, entity); - } else { - GenProcsData gen_proc_data = {}; - gen_proc_data.procs = array_make(heap_allocator()); - array_add(&gen_proc_data.procs, entity); - map_set(&info->gen_procs, base_entity->identifier.load(), gen_proc_data); - - // @@GPM - mutex_unlock(&info->gen_procs_mutex); + MUTEX_GUARD_BLOCK(&gen_procs->mutex) { + array_add(&gen_procs->procs, entity); } ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); diff --git a/src/checker.hpp b/src/checker.hpp index 04cb1e311..cc92fce28 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -369,7 +369,7 @@ struct CheckerInfo { RecursiveMutex gen_procs_mutex; RecursiveMutex gen_types_mutex; - PtrMap gen_procs; // Key: Ast * | Identifier -> Entity + PtrMap gen_procs; // Key: Ast * | Identifier -> Entity PtrMap > gen_types; BlockingMutex type_info_mutex; // NOT recursive diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 8742423a5..2703c511a 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -57,8 +57,9 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) if (pl->body != nullptr) { auto *found = map_get(&info->gen_procs, ident); if (found) { - MUTEX_GUARD(&found->mutex); - for (Entity *e : found->procs) { + GenProcsData *gpd = *found; + MUTEX_GUARD(&gpd->mutex); + for (Entity *e : gpd->procs) { if (!ptr_set_exists(min_dep_set, e)) { continue; } -- cgit v1.2.3 From e10fe91ebacdf6256608672a805de9d376e698fe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 23:50:48 +0000 Subject: Narrow global `gen_procs_mutex` further --- src/check_expr.cpp | 9 +++------ src/checker.cpp | 1 + src/thread_pool.cpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 65a411dc1..e3c55870c 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -439,7 +439,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E // @@GPM ////////////////////////// mutex_lock(&info->gen_procs_mutex); /////////////////////////////////// - auto *found = map_get(&info->gen_procs, base_entity->identifier.load()); if (found) { gen_procs = *found; @@ -462,6 +461,9 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E gen_procs->procs.allocator = heap_allocator(); map_set(&info->gen_procs, base_entity->identifier.load(), gen_procs); } + // @@GPM //////////////////////////// + mutex_unlock(&info->gen_procs_mutex); + ///////////////////////////////////// { // LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice @@ -475,11 +477,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E // LEAK TODO(bill): Cloning this AST may be leaky Ast *cloned_proc_type_node = clone_ast(pt->node); success = check_procedure_type(&nctx, final_proc_type, cloned_proc_type_node, &operands); - - // @@GPM //////////////////////////// - mutex_unlock(&info->gen_procs_mutex); - ///////////////////////////////////// - if (!success) { return false; } diff --git a/src/checker.cpp b/src/checker.cpp index c2cd1163a..ccd0f3627 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -51,6 +51,7 @@ gb_internal bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *f gb_internal void scope_reset(Scope *scope) { if (scope == nullptr) return; + MUTEX_GUARD(&scope->mutex); scope->head_child.store(nullptr, std::memory_order_relaxed); string_map_clear(&scope->elements); ptr_set_clear(&scope->imported); diff --git a/src/thread_pool.cpp b/src/thread_pool.cpp index b89e00454..07ab3d323 100644 --- a/src/thread_pool.cpp +++ b/src/thread_pool.cpp @@ -167,7 +167,7 @@ gb_internal THREAD_PROC(thread_pool_thread_proc) { idx = (idx + 1) % cast(usize)pool->threads.count; Thread *thread = &pool->threads.data[idx]; - WorkerTask task, another_task; + WorkerTask task; if (!thread_pool_queue_pop(thread, &task)) { continue; } -- cgit v1.2.3 From 670274ad8fc5ba52ea11c2d864d1915e107cc0e2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 23:56:37 +0000 Subject: More explicit uses of mutexes --- src/check_expr.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e3c55870c..3c998fc44 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -442,10 +442,11 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E auto *found = map_get(&info->gen_procs, base_entity->identifier.load()); if (found) { gen_procs = *found; - MUTEX_GUARD(&gen_procs->mutex); + mutex_lock(&gen_procs->mutex); // @local-mutex for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { + mutex_unlock(&gen_procs->mutex); // @local-mutex // @@GPM //////////////////////////// mutex_unlock(&info->gen_procs_mutex); ///////////////////////////////////// @@ -456,6 +457,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } + mutex_unlock(&gen_procs->mutex); // @local-mutex } else { gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); gen_procs->procs.allocator = heap_allocator(); @@ -481,10 +483,12 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return false; } - MUTEX_GUARD(&gen_procs->mutex); + mutex_lock(&gen_procs->mutex); // @local-mutex for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { + mutex_unlock(&gen_procs->mutex); // @local-mutex + if (poly_proc_data) { poly_proc_data->gen_entity = other; } @@ -507,6 +511,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } + mutex_unlock(&gen_procs->mutex); // @local-mutex } @@ -566,9 +571,9 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } } - MUTEX_GUARD_BLOCK(&gen_procs->mutex) { + mutex_lock(&gen_procs->mutex); // @local-mutex array_add(&gen_procs->procs, entity); - } + mutex_unlock(&gen_procs->mutex); // @local-mutex ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); proc_info->file = file; -- cgit v1.2.3 From 600f2b7284b8974a18827242c18e790dab0cf06a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 11:53:59 +0000 Subject: Use heap_allocator for all hash set types --- src/build_settings.cpp | 2 +- src/check_builtin.cpp | 2 +- src/check_decl.cpp | 2 +- src/check_expr.cpp | 1 - src/check_stmt.cpp | 1 - src/checker.cpp | 24 +++++++----------------- src/llvm_backend_general.cpp | 2 +- src/llvm_backend_type.cpp | 2 +- src/main.cpp | 8 ++++---- src/parser.cpp | 2 +- src/ptr_set.cpp | 21 +++++++++++++++------ src/string_set.cpp | 18 +++++++++++++----- 12 files changed, 45 insertions(+), 40 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 04d1ada93..75615a901 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1369,7 +1369,7 @@ gb_internal bool init_build_paths(String init_filename) { // NOTE(Jeroen): We're pre-allocating BuildPathCOUNT slots so that certain paths are always at the same enumerated index. array_init(&bc->build_paths, permanent_allocator(), BuildPathCOUNT); - string_set_init(&bc->target_features_set, heap_allocator(), 1024); + string_set_init(&bc->target_features_set, 1024); // [BuildPathMainPackage] Turn given init path into a `Path`, which includes normalizing it into a full path. bc->build_paths[BuildPath_Main_Package] = path_from_string(ha, init_filename); diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 99d956f5e..36dc9b7a1 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3086,7 +3086,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } } StringSet name_set = {}; - string_set_init(&name_set, heap_allocator(), 2*ce->args.count); + string_set_init(&name_set, 2*ce->args.count); for_array(i, ce->args) { String name = {}; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index e3486924c..0c1a7c325 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1235,7 +1235,7 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, pg_entity->type = t_invalid; PtrSet entity_set = {}; - ptr_set_init(&entity_set, heap_allocator(), 2*pg->args.count); + ptr_set_init(&entity_set, 2*pg->args.count); for_array(i, pg->args) { Ast *arg = pg->args[i]; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3c998fc44..7a00b5353 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -196,7 +196,6 @@ gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, b MUTEX_GUARD(objc_metadata->mutex); StringSet set = {}; - string_set_init(&set, heap_allocator()); defer (string_set_destroy(&set)); populate_check_did_you_mean_objc_entity(&set, e, is_type); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index cf111e84c..945ba8f02 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1185,7 +1185,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ } PtrSet seen = {}; - ptr_set_init(&seen, heap_allocator()); defer (ptr_set_destroy(&seen)); for_array(i, bs->stmts) { diff --git a/src/checker.cpp b/src/checker.cpp index ccd0f3627..8da659461 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -72,7 +72,7 @@ gb_internal void entity_graph_node_set_destroy(EntityGraphNodeSet *s) { gb_internal void entity_graph_node_set_add(EntityGraphNodeSet *s, EntityGraphNode *n) { if (s->hashes.data == nullptr) { - ptr_set_init(s, heap_allocator()); + ptr_set_init(s); } ptr_set_add(s, n); } @@ -118,15 +118,10 @@ gb_internal void entity_graph_node_swap(EntityGraphNode **data, isize i, isize j gb_internal void import_graph_node_set_destroy(ImportGraphNodeSet *s) { - if (s->hashes.data != nullptr) { - ptr_set_destroy(s); - } + ptr_set_destroy(s); } gb_internal void import_graph_node_set_add(ImportGraphNodeSet *s, ImportGraphNode *n) { - if (s->hashes.data == nullptr) { - ptr_set_init(s, heap_allocator()); - } ptr_set_add(s, n); } @@ -185,8 +180,8 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { gb_zero_item(d); d->parent = parent; d->scope = scope; - ptr_set_init(&d->deps, heap_allocator()); - ptr_set_init(&d->type_info_deps, heap_allocator()); + ptr_set_init(&d->deps); + ptr_set_init(&d->type_info_deps); array_init (&d->labels, heap_allocator()); } @@ -227,7 +222,7 @@ gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_ele Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; string_map_init(&s->elements, heap_allocator(), init_elements_capacity); - ptr_set_init(&s->imported, heap_allocator(), 0); + ptr_set_init(&s->imported, 0); if (parent != nullptr && parent != builtin_pkg->scope) { Scope *prev_head_child = parent->head_child.exchange(s, std::memory_order_acq_rel); @@ -2270,8 +2265,8 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { isize entity_count = c->info.entities.count; isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor - ptr_set_init(&c->info.minimum_dependency_set, heap_allocator(), min_dep_set_cap); - ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator()); + ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); + ptr_set_init(&c->info.minimum_dependency_type_info_set); #define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ if (condition) { \ @@ -3388,7 +3383,6 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array const &at } StringSet set = {}; - string_set_init(&set, heap_allocator()); defer (string_set_destroy(&set)); for_array(i, attributes) { @@ -4759,7 +4753,6 @@ gb_internal void check_import_entities(Checker *c) { auto pq = priority_queue_create(dep_graph, import_graph_node_cmp, import_graph_node_swap); PtrSet emitted = {}; - ptr_set_init(&emitted, heap_allocator()); defer (ptr_set_destroy(&emitted)); Array package_order = {}; @@ -4773,7 +4766,6 @@ gb_internal void check_import_entities(Checker *c) { if (n->dep_count > 0) { PtrSet visited = {}; - ptr_set_init(&visited, heap_allocator()); defer (ptr_set_destroy(&visited)); auto path = find_import_path(c, pkg, pkg, &visited); @@ -4927,7 +4919,6 @@ gb_internal Array find_entity_path(Entity *start, Entity *end, PtrSet< bool made_visited = false; if (visited == nullptr) { made_visited = true; - ptr_set_init(&visited_, heap_allocator()); visited = &visited_; } defer (if (made_visited) { @@ -4990,7 +4981,6 @@ gb_internal void calculate_global_init_order(Checker *c) { auto pq = priority_queue_create(dep_graph, entity_graph_node_cmp, entity_graph_node_swap); PtrSet emitted = {}; - ptr_set_init(&emitted, heap_allocator()); defer (ptr_set_destroy(&emitted)); TIME_SECTION("calculate_global_init_order: queue sort"); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 22628e895..75675474a 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -133,7 +133,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { array_init(&gen->foreign_libraries, heap_allocator(), 0, 1024); - ptr_set_init(&gen->foreign_libraries_set, heap_allocator(), 1024); + ptr_set_init(&gen->foreign_libraries_set, 1024); if (USE_SEPARATE_MODULES) { for (auto const &entry : gen->info->packages) { diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 26bb614e6..c306cdead 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -2,7 +2,7 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_ auto *set = &info->minimum_dependency_type_info_set; isize index = type_info_index(info, type, err_on_not_found); if (index >= 0) { - isize i = ptr_entry_index(set, index); + isize i = ptr_set_entry_index(set, index); if (i >= 0) { return i+1; } diff --git a/src/main.cpp b/src/main.cpp index ad9d6b0ef..91dcbdb01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -212,11 +212,11 @@ gb_internal i32 linker_stage(lbGenerator *gen) { StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); StringSet asm_files = {}; - string_set_init(&asm_files, heap_allocator(), 64); + string_set_init(&asm_files, 64); defer (string_set_destroy(&asm_files)); for_array(j, gen->foreign_libraries) { @@ -371,7 +371,7 @@ gb_internal i32 linker_stage(lbGenerator *gen) { defer (gb_string_free(lib_str)); StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); for_array(j, gen->foreign_libraries) { @@ -2518,7 +2518,7 @@ int main(int arg_count, char const **arg_ptr) { map_init(&build_context.defined_values, heap_allocator()); build_context.extra_packages.allocator = heap_allocator(); - string_set_init(&build_context.test_names, heap_allocator()); + string_set_init(&build_context.test_names); Array args = setup_args(arg_count, arg_ptr); diff --git a/src/parser.cpp b/src/parser.cpp index 4d2a8ecf4..046469c16 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -4854,7 +4854,7 @@ gb_internal void destroy_ast_file(AstFile *f) { gb_internal bool init_parser(Parser *p) { GB_ASSERT(p != nullptr); - string_set_init(&p->imported_files, heap_allocator()); + string_set_init(&p->imported_files); array_init(&p->packages, heap_allocator()); return true; } diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 9ecf1043e..affde5c2f 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -6,11 +6,11 @@ struct PtrSetEntry { template struct PtrSet { - Slice hashes; + Slice hashes; Array> entries; }; -template gb_internal void ptr_set_init (PtrSet *s, gbAllocator a, isize capacity = 16); +template gb_internal void ptr_set_init (PtrSet *s, isize capacity = 16); template gb_internal void ptr_set_destroy(PtrSet *s); template gb_internal T ptr_set_add (PtrSet *s, T ptr); template gb_internal bool ptr_set_update (PtrSet *s, T ptr); // returns true if it previously existed @@ -21,15 +21,18 @@ template gb_internal void ptr_set_grow (PtrSet *s); template gb_internal void ptr_set_rehash (PtrSet *s, isize new_count); template gb_internal void ptr_set_reserve(PtrSet *h, isize cap); +gb_internal gbAllocator ptr_set_allocator(void) { + return heap_allocator(); +} template -gb_internal void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { +gb_internal void ptr_set_init(PtrSet *s, isize capacity) { if (capacity != 0) { capacity = next_pow2_isize(gb_max(16, capacity)); } - slice_init(&s->hashes, a, capacity); - array_init(&s->entries, a, 0, capacity); + slice_init(&s->hashes, ptr_set_allocator(), capacity); + array_init(&s->entries, ptr_set_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { s->hashes.data[i] = MAP_SENTINEL; } @@ -37,6 +40,9 @@ gb_internal void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { template gb_internal void ptr_set_destroy(PtrSet *s) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = ptr_set_allocator(); + } slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); } @@ -118,6 +124,9 @@ gb_internal void ptr_set_reset_entries(PtrSet *s) { template gb_internal void ptr_set_reserve(PtrSet *s, isize cap) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = ptr_set_allocator(); + } array_reserve(&s->entries, cap); if (s->entries.count*2 < s->hashes.count) { return; @@ -139,7 +148,7 @@ gb_internal gb_inline bool ptr_set_exists(PtrSet *s, T ptr) { } template -gb_internal gb_inline isize ptr_entry_index(PtrSet *s, T ptr) { +gb_internal gb_inline isize ptr_set_entry_index(PtrSet *s, T ptr) { isize index = ptr_set__find(s, ptr).entry_index; if (index != MAP_SENTINEL) { return index; diff --git a/src/string_set.cpp b/src/string_set.cpp index 1c97d253e..753afa9bf 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -10,7 +10,7 @@ struct StringSet { }; -gb_internal void string_set_init (StringSet *s, gbAllocator a, isize capacity = 16); +gb_internal void string_set_init (StringSet *s, isize capacity = 16); gb_internal void string_set_destroy(StringSet *s); gb_internal void string_set_add (StringSet *s, String const &str); gb_internal bool string_set_update (StringSet *s, String const &str); // returns true if it previously existed @@ -20,18 +20,24 @@ gb_internal void string_set_clear (StringSet *s); gb_internal void string_set_grow (StringSet *s); gb_internal void string_set_rehash (StringSet *s, isize new_count); +gb_internal gbAllocator string_set_allocator(void) { + return heap_allocator(); +} -gb_internal gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) { +gb_internal gb_inline void string_set_init(StringSet *s, isize capacity) { capacity = next_pow2_isize(gb_max(16, capacity)); - slice_init(&s->hashes, a, capacity); - array_init(&s->entries, a, 0, capacity); + slice_init(&s->hashes, string_set_allocator(), capacity); + array_init(&s->entries, string_set_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { s->hashes.data[i] = MAP_SENTINEL; } } gb_internal gb_inline void string_set_destroy(StringSet *s) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = string_set_allocator(); + } slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); } @@ -106,6 +112,9 @@ gb_internal void string_set_reset_entries(StringSet *s) { } gb_internal void string_set_reserve(StringSet *s, isize cap) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = string_set_allocator(); + } array_reserve(&s->entries, cap); if (s->entries.count*2 < s->hashes.count) { return; @@ -217,7 +226,6 @@ gb_internal gb_inline void string_set_clear(StringSet *s) { } - gb_internal StringSetEntry *begin(StringSet &m) { return m.entries.data; } -- cgit v1.2.3 From 252be0fb417f9cdde5e9c4b348cd995a20433aea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 11:59:52 +0000 Subject: Make all maps use heap allocator implicitly --- src/check_builtin.cpp | 2 +- src/check_expr.cpp | 3 +-- src/check_stmt.cpp | 1 - src/checker.cpp | 33 +++++++++++++++------------------ src/common.cpp | 2 +- src/docs_writer.cpp | 11 +++++------ src/llvm_backend_general.cpp | 44 ++++++++++++++++++++++---------------------- src/llvm_backend_proc.cpp | 10 +++++----- src/main.cpp | 2 +- src/ptr_map.cpp | 18 ++++++++++++++---- src/string_map.cpp | 18 ++++++++++++++---- 11 files changed, 79 insertions(+), 65 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 36dc9b7a1..af196234e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1110,7 +1110,7 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String new_cache->path = path; new_cache->data = data; new_cache->file_error = file_error; - string_map_init(&new_cache->hashes, heap_allocator(), 32); + string_map_init(&new_cache->hashes, 32); string_map_set(&c->info->load_file_cache, path, new_cache); if (cache_) *cache_ = new_cache; } else { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7a00b5353..030bfb8e6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5753,7 +5753,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op // in order to improve the type inference system StringMap type_hint_map = {}; // Key: String - string_map_init(&type_hint_map, heap_allocator(), 2*args.count); + string_map_init(&type_hint_map, 2*args.count); defer (string_map_destroy(&type_hint_map)); Type *ptype = nullptr; @@ -8283,7 +8283,6 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * bool is_partial = cl->tag && (cl->tag->BasicDirective.name.string == "partial"); SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue - map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 945ba8f02..7192b16b5 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -929,7 +929,6 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags } SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue - map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); for_array(stmt_index, bs->stmts) { diff --git a/src/checker.cpp b/src/checker.cpp index 8da659461..8779d9d45 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -221,7 +221,7 @@ gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) { gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CAPACITY) { Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; - string_map_init(&s->elements, heap_allocator(), init_elements_capacity); + string_map_init(&s->elements, init_elements_capacity); ptr_set_init(&s->imported, 0); if (parent != nullptr && parent != builtin_pkg->scope) { @@ -1135,14 +1135,14 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->definitions, a); array_init(&i->entities, a); - map_init(&i->global_untyped, a); - string_map_init(&i->foreigns, a); - map_init(&i->gen_procs, a); - map_init(&i->gen_types, a); + map_init(&i->global_untyped); + string_map_init(&i->foreigns); + map_init(&i->gen_procs); + map_init(&i->gen_types); array_init(&i->type_info_types, a); - map_init(&i->type_info_map, a); - string_map_init(&i->files, a); - string_map_init(&i->packages, a); + map_init(&i->type_info_map); + string_map_init(&i->files); + string_map_init(&i->packages); array_init(&i->variable_init_order, a); array_init(&i->testing_procedures, a, 0, 0); array_init(&i->init_procedures, a, 0, 0); @@ -1160,8 +1160,8 @@ gb_internal void init_checker_info(CheckerInfo *i) { mpmc_init(&i->intrinsics_entry_point_usage, a, 1<<10); // just waste some memory here, even if it probably never used - map_init(&i->objc_msgSend_types, a); - string_map_init(&i->load_file_cache, a); + map_init(&i->objc_msgSend_types); + string_map_init(&i->load_file_cache); array_init(&i->all_procedures, heap_allocator()); @@ -2490,7 +2490,7 @@ gb_internal bool is_entity_a_dependency(Entity *e) { gb_internal Array generate_entity_dependency_graph(CheckerInfo *info, gbAllocator allocator) { PtrMap M = {}; - map_init(&M, allocator, info->entities.count); + map_init(&M, info->entities.count); defer (map_destroy(&M)); for_array(i, info->entities) { Entity *e = info->entities[i]; @@ -4200,7 +4200,7 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMap generate_import_dependency_graph(Checker *c) { PtrMap M = {}; - map_init(&M, heap_allocator(), 2*c->parser->packages.count); + map_init(&M, 2*c->parser->packages.count); defer (map_destroy(&M)); for_array(i, c->parser->packages) { @@ -4688,7 +4688,7 @@ gb_internal void check_collect_entities_all(Checker *c) { auto *wd = &collect_entity_worker_data[i]; wd->c = c; wd->ctx = make_checker_context(c); - map_init(&wd->untyped, heap_allocator()); + map_init(&wd->untyped); } for (auto const &entry : c->info.files.entries) { @@ -4804,7 +4804,6 @@ gb_internal void check_import_entities(Checker *c) { CheckerContext ctx = make_checker_context(c); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); isize min_pkg_index = 0; @@ -5159,7 +5158,6 @@ gb_internal void check_unchecked_bodies(Checker *c) { GB_ASSERT(c->procs_to_check.count == 0); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); // use the `procs_to_check` array @@ -5212,7 +5210,6 @@ gb_internal void check_unchecked_bodies(Checker *c) { gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) { GB_ASSERT(DEBUG_CHECK_ALL_PROCEDURES); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); @@ -5345,7 +5342,7 @@ gb_internal void check_procedure_bodies(Checker *c) { for (isize i = 0; i < thread_count; i++) { check_procedure_bodies_worker_data[i].c = c; - map_init(&check_procedure_bodies_worker_data[i].untyped, heap_allocator()); + map_init(&check_procedure_bodies_worker_data[i].untyped); } defer (for (isize i = 0; i < thread_count; i++) { @@ -5545,7 +5542,7 @@ gb_internal void check_deferred_procedures(Checker *c) { gb_internal void check_unique_package_names(Checker *c) { StringMap pkgs = {}; // Key: package name - string_map_init(&pkgs, heap_allocator(), 2*c->info.packages.entries.count); + string_map_init(&pkgs, 2*c->info.packages.entries.count); defer (string_map_destroy(&pkgs)); for (auto const &entry : c->info.packages) { diff --git a/src/common.cpp b/src/common.cpp index 3b6ea59e8..199a263a1 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -373,7 +373,7 @@ gb_internal char const *string_intern(String const &string) { } gb_internal void init_string_interner(void) { - map_init(&string_intern_map, heap_allocator()); + map_init(&string_intern_map); } diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index bab97158d..2aefe29eb 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -53,13 +53,12 @@ gb_internal void odin_doc_writer_item_tracker_init(OdinDocWriterItemTracker * gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) { w->state = OdinDocWriterState_Preparing; - gbAllocator a = heap_allocator(); - string_map_init(&w->string_cache, a); + string_map_init(&w->string_cache); - map_init(&w->file_cache, a); - map_init(&w->pkg_cache, a); - map_init(&w->entity_cache, a); - map_init(&w->type_cache, a); + map_init(&w->file_cache); + map_init(&w->pkg_cache); + map_init(&w->entity_cache); + map_init(&w->type_cache); odin_doc_writer_item_tracker_init(&w->files, 1); odin_doc_writer_item_tracker_init(&w->pkgs, 1); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 75675474a..a849929f0 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -55,30 +55,30 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { } gbAllocator a = heap_allocator(); - map_init(&m->types, a); - map_init(&m->func_raw_types, a); - map_init(&m->struct_field_remapping, a); - map_init(&m->values, a); - map_init(&m->soa_values, a); - string_map_init(&m->members, a); - map_init(&m->procedure_values, a); - string_map_init(&m->procedures, a); - string_map_init(&m->const_strings, a); - map_init(&m->function_type_map, a); - map_init(&m->equal_procs, a); - map_init(&m->hasher_procs, a); - map_init(&m->map_get_procs, a); - map_init(&m->map_set_procs, a); + map_init(&m->types); + map_init(&m->func_raw_types); + map_init(&m->struct_field_remapping); + map_init(&m->values); + map_init(&m->soa_values); + string_map_init(&m->members); + map_init(&m->procedure_values); + string_map_init(&m->procedures); + string_map_init(&m->const_strings); + map_init(&m->function_type_map); + map_init(&m->equal_procs); + map_init(&m->hasher_procs); + map_init(&m->map_get_procs); + map_init(&m->map_set_procs); array_init(&m->procedures_to_generate, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); - map_init(&m->debug_values, a); + map_init(&m->debug_values); array_init(&m->debug_incomplete_types, a, 0, 1024); - string_map_init(&m->objc_classes, a); - string_map_init(&m->objc_selectors, a); + string_map_init(&m->objc_classes); + string_map_init(&m->objc_selectors); - map_init(&m->map_info_map, a, 0); - map_init(&m->map_cell_info_map, a, 0); + map_init(&m->map_info_map, 0); + map_init(&m->map_cell_info_map, 0); } @@ -127,9 +127,9 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { gen->info = &c->info; - map_init(&gen->modules, permanent_allocator(), gen->info->packages.entries.count*2); - map_init(&gen->modules_through_ctx, permanent_allocator(), gen->info->packages.entries.count*2); - map_init(&gen->anonymous_proc_lits, heap_allocator(), 1024); + map_init(&gen->modules, gen->info->packages.entries.count*2); + map_init(&gen->modules_through_ctx, gen->info->packages.entries.count*2); + map_init(&gen->anonymous_proc_lits, 1024); array_init(&gen->foreign_libraries, heap_allocator(), 0, 1024); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 7245bdd80..c66462bc1 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -119,9 +119,9 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i p->branch_blocks.allocator = a; p->context_stack.allocator = a; p->scope_stack.allocator = a; - map_init(&p->selector_values, a, 0); - map_init(&p->selector_addr, a, 0); - map_init(&p->tuple_fix_map, a, 0); + map_init(&p->selector_values, 0); + map_init(&p->selector_addr, 0); + map_init(&p->tuple_fix_map, 0); if (p->is_foreign) { lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library); @@ -345,7 +345,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name p->blocks.allocator = a; p->branch_blocks.allocator = a; p->context_stack.allocator = a; - map_init(&p->tuple_fix_map, a, 0); + map_init(&p->tuple_fix_map, 0); char *c_link_name = alloc_cstring(permanent_allocator(), p->name); @@ -486,7 +486,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { p->entry_block = lb_create_block(p, "entry", true); lb_start_block(p, p->entry_block); - map_init(&p->direct_parameters, heap_allocator()); + map_init(&p->direct_parameters); GB_ASSERT(p->type != nullptr); diff --git a/src/main.cpp b/src/main.cpp index 91dcbdb01..7ac78241e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2516,7 +2516,7 @@ int main(int arg_count, char const **arg_ptr) { add_library_collection(str_lit("core"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("core"))); add_library_collection(str_lit("vendor"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("vendor"))); - map_init(&build_context.defined_values, heap_allocator()); + map_init(&build_context.defined_values); build_context.extra_packages.allocator = heap_allocator(); string_set_init(&build_context.test_names); diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 434680e91..083cd6697 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -46,7 +46,7 @@ gb_internal gb_inline u32 ptr_map_hash_key(void const *key) { } -template gb_internal void map_init (PtrMap *h, gbAllocator a, isize capacity = 16); +template gb_internal void map_init (PtrMap *h, isize capacity = 16); template gb_internal void map_destroy (PtrMap *h); template gb_internal V * map_get (PtrMap *h, K key); template gb_internal void map_set (PtrMap *h, K key, V const &value); @@ -68,11 +68,15 @@ template gb_internal void multi_map_remove (PtrMap< template gb_internal void multi_map_remove_all(PtrMap *h, K key); #endif +gb_internal gbAllocator map_allocator(void) { + return heap_allocator(); +} + template -gb_internal gb_inline void map_init(PtrMap *h, gbAllocator a, isize capacity) { +gb_internal gb_inline void map_init(PtrMap *h, isize capacity) { capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); + slice_init(&h->hashes, map_allocator(), capacity); + array_init(&h->entries, map_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { h->hashes.data[i] = MAP_SENTINEL; } @@ -80,6 +84,9 @@ gb_internal gb_inline void map_init(PtrMap *h, gbAllocator a, isize capaci template gb_internal gb_inline void map_destroy(PtrMap *h) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = map_allocator(); + } slice_free(&h->hashes, h->entries.allocator); array_free(&h->entries); } @@ -162,6 +169,9 @@ gb_internal void map_reset_entries(PtrMap *h) { template gb_internal void map_reserve(PtrMap *h, isize cap) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = map_allocator(); + } array_reserve(&h->entries, cap); if (h->entries.count*2 < h->hashes.count) { return; diff --git a/src/string_map.cpp b/src/string_map.cpp index 9f9374ece..b5db63e90 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -35,7 +35,7 @@ struct StringMap { }; -template gb_internal void string_map_init (StringMap *h, gbAllocator a, isize capacity = 16); +template gb_internal void string_map_init (StringMap *h, isize capacity = 16); template gb_internal void string_map_destroy (StringMap *h); template gb_internal T * string_map_get (StringMap *h, char const *key); @@ -56,11 +56,15 @@ template gb_internal void string_map_grow (StringMap template gb_internal void string_map_rehash (StringMap *h, isize new_count); template gb_internal void string_map_reserve (StringMap *h, isize cap); +gb_internal gbAllocator string_map_allocator(void) { + return heap_allocator(); +} + template -gb_internal gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { +gb_internal gb_inline void string_map_init(StringMap *h, isize capacity) { capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); + slice_init(&h->hashes, string_map_allocator(), capacity); + array_init(&h->entries, string_map_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { h->hashes.data[i] = MAP_SENTINEL; } @@ -68,6 +72,9 @@ gb_internal gb_inline void string_map_init(StringMap *h, gbAllocator a, isize template gb_internal gb_inline void string_map_destroy(StringMap *h) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = string_map_allocator(); + } slice_free(&h->hashes, h->entries.allocator); array_free(&h->entries); } @@ -147,6 +154,9 @@ gb_internal void string_map_reset_entries(StringMap *h) { template gb_internal void string_map_reserve(StringMap *h, isize cap) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = string_map_allocator(); + } array_reserve(&h->entries, cap); if (h->entries.count*2 < h->hashes.count) { return; -- cgit v1.2.3 From 747a11a954824da7960a247299986f56d1316773 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 12:18:35 +0000 Subject: Allow all set entry types to be implicitly cast to their key/value type to allow for easier iteration --- src/build_settings.cpp | 6 ++---- src/check_decl.cpp | 6 ++---- src/check_expr.cpp | 7 +++---- src/checker.cpp | 38 +++++++++++++------------------------- src/ptr_set.cpp | 12 ++++++++---- src/string_map.cpp | 13 ++++++++++--- src/string_set.cpp | 15 +++++++++++---- src/types.cpp | 3 +-- 8 files changed, 50 insertions(+), 50 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 75615a901..1dff5f43e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1332,11 +1332,10 @@ gb_internal void enable_target_feature(TokenPos pos, String const &target_featur gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bool with_quotes) { isize len = 0; isize i = 0; - for (auto const &entry : build_context.target_features_set) { + for (String const &feature : build_context.target_features_set) { if (i != 0) { len += 1; } - String feature = entry.value; len += feature.len; if (with_quotes) len += 2; i += 1; @@ -1344,13 +1343,12 @@ gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bo char *features = gb_alloc_array(allocator, char, len+1); len = 0; i = 0; - for (auto const &entry : build_context.target_features_set) { + for (String const &feature : build_context.target_features_set) { if (i != 0) { features[len++] = ','; } if (with_quotes) features[len++] = '"'; - String feature = entry.value; gb_memmove(features + len, feature.text, feature.len); len += feature.len; if (with_quotes) features[len++] = '"'; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 0c1a7c325..7b229db08 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1587,16 +1587,14 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de MUTEX_GUARD_BLOCK(decl->deps_mutex) MUTEX_GUARD_BLOCK(decl->parent->deps_mutex) { - for (auto const &entry : decl->deps) { - Entity *e = entry.ptr; + for (Entity *e : decl->deps) { ptr_set_add(&decl->parent->deps, e); } } MUTEX_GUARD_BLOCK(decl->type_info_deps_mutex) MUTEX_GUARD_BLOCK(decl->parent->type_info_deps_mutex) { - for (auto const &entry : decl->type_info_deps) { - Type *t = entry.ptr; + for (Type *t : decl->type_info_deps) { ptr_set_add(&decl->parent->type_info_deps, t); } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 030bfb8e6..2924f9d13 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -202,8 +202,8 @@ gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, b DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), set.entries.count, name); defer (did_you_mean_destroy(&d)); - for (auto const &entry : set) { - did_you_mean_append(&d, entry.value); + for (String const &target : set) { + did_you_mean_append(&d, target); } check_did_you_mean_print(&d, prefix); } @@ -4942,8 +4942,7 @@ gb_internal isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lh if (e != nullptr) { DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { - for (auto const &entry : decl->deps) { - Entity *dep = entry.ptr; + for (Entity *dep : decl->deps) { ptr_set_add(&c->decl->deps, dep); } } diff --git a/src/checker.cpp b/src/checker.cpp index 8779d9d45..0075fa543 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2222,12 +2222,11 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { return; } - for (auto const &entry : decl->type_info_deps) { - add_min_dep_type_info(c, entry.ptr); + for (Type *t : decl->type_info_deps) { + add_min_dep_type_info(c, t); } - for (auto const &entry : decl->deps) { - Entity *e = entry.ptr; + for (Entity *e : decl->deps) { add_dependency_to_set(c, e); if (e->kind == Entity_Procedure && e->Procedure.is_foreign) { Entity *fl = e->Procedure.foreign_library; @@ -2510,8 +2509,7 @@ gb_internal Array generate_entity_dependency_graph(CheckerInf DeclInfo *decl = decl_info_of_entity(e); GB_ASSERT(decl != nullptr); - for (auto const &entry : decl->deps) { - Entity *dep = entry.ptr; + for (Entity *dep : decl->deps) { if (dep->flags & EntityFlag_Field) { continue; } @@ -2537,15 +2535,12 @@ gb_internal Array generate_entity_dependency_graph(CheckerInf if (e->kind == Entity_Procedure) { // Connect each pred 'p' of 'n' with each succ 's' and from // the procedure node - for (auto const &p_entry : n->pred) { - EntityGraphNode *p = p_entry.ptr; - + for (EntityGraphNode *p : n->pred) { // Ignore self-cycles if (p != n) { // Each succ 's' of 'n' becomes a succ of 'p', and // each pred 'p' of 'n' becomes a pred of 's' - for (auto const &s_entry : n->succ) { - EntityGraphNode *s = s_entry.ptr; + for (EntityGraphNode *s : n->succ) { // Ignore self-cycles if (s != n) { if (p->entity->kind == Entity_Procedure && @@ -4784,8 +4779,7 @@ gb_internal void check_import_entities(Checker *c) { } } - for (auto const &entry : n->pred) { - ImportGraphNode *p = entry.ptr; + for (ImportGraphNode *p : n->pred) { p->dep_count = gb_max(p->dep_count-1, 0); priority_queue_fix(&pq, p->index); } @@ -4893,8 +4887,7 @@ gb_internal bool find_entity_path_tuple(Type *tuple, Entity *end, PtrSetdeps) { - Entity *dep = entry.ptr; + for (Entity *dep : var_decl->deps) { if (dep == end) { auto path = array_make(heap_allocator()); array_add(&path, dep); @@ -4944,8 +4937,7 @@ gb_internal Array find_entity_path(Entity *start, Entity *end, PtrSet< return path; } } else { - for (auto const &entry : decl->deps) { - Entity *dep = entry.ptr; + for (Entity *dep : decl->deps) { if (dep == end) { auto path = array_make(heap_allocator()); array_add(&path, dep); @@ -5002,8 +4994,7 @@ gb_internal void calculate_global_init_order(Checker *c) { } } - for (auto const &entry : n->pred) { - EntityGraphNode *p = entry.ptr; + for (EntityGraphNode *p : n->pred) { p->dep_count -= 1; p->dep_count = gb_max(p->dep_count, 0); priority_queue_fix(&pq, p->index); @@ -5163,8 +5154,7 @@ gb_internal void check_unchecked_bodies(Checker *c) { // use the `procs_to_check` array global_procedure_body_in_worker_queue = false; - for (auto const &entry : c->info.minimum_dependency_set) { - Entity *e = entry.ptr; + for (Entity *e : c->info.minimum_dependency_set) { if (e == nullptr || e->kind != Entity_Procedure) { continue; } @@ -5239,8 +5229,7 @@ gb_internal void check_test_procedures(Checker *c) { AstPackage *pkg = c->info.init_package; Scope *s = pkg->scope; - for (auto const &entry : build_context.test_names) { - String name = entry.value; + for (String const &name : build_context.test_names) { Entity *e = scope_lookup(s, name); if (e == nullptr) { Token tok = {}; @@ -5744,8 +5733,7 @@ gb_internal void check_parsed_files(Checker *c) { DeclInfo *decl = e->decl_info; ast_node(pl, ProcLit, decl->proc_lit); if (pl->inlining == ProcInlining_inline) { - for (auto const &entry : decl->deps) { - Entity *dep = entry.ptr; + for (Entity *dep : decl->deps) { if (dep == e) { error(e->token, "Cannot inline recursive procedure '%.*s'", LIT(e->token.string)); break; diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index affde5c2f..303bde07e 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -2,6 +2,10 @@ template struct PtrSetEntry { T ptr; MapIndex next; + + operator T() const noexcept { + return this->ptr; + } }; template @@ -245,21 +249,21 @@ gb_internal gb_inline void ptr_set_clear(PtrSet *s) { template -gb_internal PtrSetEntry *begin(PtrSet &m) { +gb_internal PtrSetEntry *begin(PtrSet &m) noexcept { return m.entries.data; } template -gb_internal PtrSetEntry const *begin(PtrSet const &m) { +gb_internal PtrSetEntry const *begin(PtrSet const &m) noexcept { return m.entries.data; } template -gb_internal PtrSetEntry *end(PtrSet &m) { +gb_internal PtrSetEntry *end(PtrSet &m) noexcept { return m.entries.data + m.entries.count; } template -gb_internal PtrSetEntry const *end(PtrSet const &m) { +gb_internal PtrSetEntry const *end(PtrSet const &m) noexcept { return m.entries.data + m.entries.count; } \ No newline at end of file diff --git a/src/string_map.cpp b/src/string_map.cpp index b5db63e90..74a16de73 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -1,6 +1,13 @@ struct StringHashKey { u32 hash; String string; + + operator String() const noexcept { + return this->string; + } + operator String const &() const noexcept { + return this->string; + } }; gb_internal gb_inline StringHashKey string_hash_string(String const &s) { @@ -283,11 +290,11 @@ gb_internal gb_inline void string_map_clear(StringMap *h) { template -gb_internal StringMapEntry *begin(StringMap &m) { +gb_internal StringMapEntry *begin(StringMap &m) noexcept { return m.entries.data; } template -gb_internal StringMapEntry const *begin(StringMap const &m) { +gb_internal StringMapEntry const *begin(StringMap const &m) noexcept { return m.entries.data; } @@ -298,6 +305,6 @@ gb_internal StringMapEntry *end(StringMap &m) { } template -gb_internal StringMapEntry const *end(StringMap const &m) { +gb_internal StringMapEntry const *end(StringMap const &m) noexcept { return m.entries.data + m.entries.count; } \ No newline at end of file diff --git a/src/string_set.cpp b/src/string_set.cpp index 753afa9bf..fb4640c20 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -2,6 +2,13 @@ struct StringSetEntry { u32 hash; MapIndex next; String value; + + operator String const() const noexcept { + return this->value; + } + operator String const &() const noexcept { + return this->value; + } }; struct StringSet { @@ -226,18 +233,18 @@ gb_internal gb_inline void string_set_clear(StringSet *s) { } -gb_internal StringSetEntry *begin(StringSet &m) { +gb_internal StringSetEntry *begin(StringSet &m) noexcept { return m.entries.data; } -gb_internal StringSetEntry const *begin(StringSet const &m) { +gb_internal StringSetEntry const *begin(StringSet const &m) noexcept { return m.entries.data; } -gb_internal StringSetEntry *end(StringSet &m) { +gb_internal StringSetEntry *end(StringSet &m) noexcept { return m.entries.data + m.entries.count; } -gb_internal StringSetEntry const *end(StringSet const &m) { +gb_internal StringSetEntry const *end(StringSet const &m) noexcept { return m.entries.data + m.entries.count; } \ No newline at end of file diff --git a/src/types.cpp b/src/types.cpp index 1e2d85ac6..d33c36e94 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -823,8 +823,7 @@ gb_internal bool type_ptr_set_exists(PtrSet *s, Type *t) { // TODO(bill, 2019-10-05): This is very slow and it's probably a lot // faster to cache types correctly - for (auto const &entry : *s) { - Type *f = entry.ptr; + for (Type *f : *s) { if (are_types_identical(t, f)) { ptr_set_add(s, t); return true; -- cgit v1.2.3 From 7380b7e61be55e4c2371f62401d6175c51ea0c6f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 12:37:41 +0000 Subject: Add more uses of C++ style `for` loops over `for_array` macro --- src/check_expr.cpp | 149 ++++++++++++++++++++--------------------------------- 1 file changed, 57 insertions(+), 92 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2924f9d13..c1787e7b6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -146,8 +146,8 @@ gb_internal void check_did_you_mean_print(DidYouMeanAnswers *d, char const *pref auto results = did_you_mean_results(d); if (results.count != 0) { error_line("\tSuggestion: Did you mean?\n"); - for_array(i, results) { - String const &target = results[i].target; + for (auto const &result : results) { + String const &target = result.target; error_line("\t\t%s%.*s\n", prefix, LIT(target)); // error_line("\t\t%.*s %td\n", LIT(target), results[i].distance); } @@ -166,19 +166,16 @@ gb_internal void populate_check_did_you_mean_objc_entity(StringSet *set, Entity GB_ASSERT(t->kind == Type_Struct); if (is_type) { - for_array(i, objc_metadata->type_entries) { - String name = objc_metadata->type_entries[i].name; - string_set_add(set, name); + for (auto const &entry : objc_metadata->type_entries) { + string_set_add(set, entry.name); } } else { - for_array(i, objc_metadata->value_entries) { - String name = objc_metadata->value_entries[i].name; - string_set_add(set, name); + for (auto const &entry : objc_metadata->value_entries) { + string_set_add(set, entry.name); } } - for_array(i, t->Struct.fields) { - Entity *f = t->Struct.fields[i]; + for (Entity *f : t->Struct.fields) { if (f->flags & EntityFlag_Using && f->type != nullptr) { if (f->type->kind == Type_Named && f->type->Named.type_name) { populate_check_did_you_mean_objc_entity(set, f->type->Named.type_name, is_type); @@ -214,8 +211,8 @@ gb_internal void check_did_you_mean_type(String const &name, Array con DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name); defer (did_you_mean_destroy(&d)); - for_array(i, fields) { - did_you_mean_append(&d, fields[i]->token.string); + for (Entity *e : fields) { + did_you_mean_append(&d, e->token.string); } check_did_you_mean_print(&d, prefix); } @@ -227,8 +224,8 @@ gb_internal void check_did_you_mean_type(String const &name, Slice con DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name); defer (did_you_mean_destroy(&d)); - for_array(i, fields) { - did_you_mean_append(&d, fields[i]->token.string); + for (Entity *e : fields) { + did_you_mean_append(&d, e->token.string); } check_did_you_mean_print(&d, prefix); } @@ -781,8 +778,7 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand } if (is_type_union(dst)) { - for_array(i, dst->Union.variants) { - Type *vt = dst->Union.variants[i]; + for (Type *vt : dst->Union.variants) { if (are_types_identical(vt, s)) { return 1; } @@ -798,8 +794,7 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand } else if (is_type_untyped(src)) { i64 prev_lowest_score = -1; i64 lowest_score = -1; - for_array(i, dst->Union.variants) { - Type *vt = dst->Union.variants[i]; + for (Type *vt : dst->Union.variants) { i64 score = check_distance_between_types(c, operand, vt); if (score >= 0) { if (lowest_score < 0) { @@ -1031,8 +1026,8 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ if (type != nullptr && is_type_proc(type)) { Array procs = proc_group_entities(c, *operand); // NOTE(bill): These should be done - for_array(i, procs) { - Type *t = base_type(procs[i]->type); + for (Entity *e : procs) { + Type *t = base_type(e->type); if (t == t_invalid) { continue; } @@ -1040,7 +1035,6 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ x.mode = Addressing_Value; x.type = t; if (check_is_assignable_to(c, &x, type)) { - Entity *e = procs[i]; add_entity_use(c, operand->expr, e); good = true; break; @@ -1470,7 +1464,7 @@ gb_internal bool check_cycle(CheckerContext *c, Entity *curr, bool report) { return false; } for_array(i, *c->type_path) { - Entity *prev = (*c->type_path)[i]; + Entity *prev = c->type_path->data[i]; if (prev == curr) { if (report) { error(curr->token, "Illegal declaration cycle of `%.*s`", LIT(curr->token.string)); @@ -1535,8 +1529,8 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam if (type_hint != nullptr && is_type_proc(type_hint)) { // NOTE(bill): These should be done - for_array(i, procs) { - Type *t = base_type(procs[i]->type); + for (Entity *proc : procs) { + Type *t = base_type(proc->type); if (t == t_invalid) { continue; } @@ -1544,7 +1538,7 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam x.mode = Addressing_Value; x.type = t; if (check_is_assignable_to(c, &x, type_hint)) { - e = procs[i]; + e = proc; add_entity_use(c, n, e); skip = true; break; @@ -4174,8 +4168,7 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v if (cl->elems[0]->kind == Ast_FieldValue) { if (is_type_struct(node->tav.type)) { bool found = false; - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { continue; } @@ -4194,8 +4187,7 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v value = {}; } } else if (is_type_array(node->tav.type) || is_type_enumerated_array(node->tav.type)) { - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { continue; } @@ -4578,8 +4570,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod if (entity->kind == Entity_ProcGroup) { Array procs = entity->ProcGroup.entities; bool skip = false; - for_array(i, procs) { - Entity *p = procs[i]; + for (Entity *p : procs) { Type *t = base_type(p->type); if (t == t_invalid) { continue; @@ -4958,7 +4949,7 @@ gb_internal isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lh gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array const &lhs, Array *operands, Slice const &rhs) { bool optional_ok = false; isize tuple_index = 0; - for_array(i, rhs) { + for (Ast *rhs_expr : rhs) { CheckerContext c_ = *ctx; CheckerContext *c = &c_; @@ -4970,7 +4961,7 @@ gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array type_hint = lhs[tuple_index].type; } - check_expr_base(c, &o, rhs[i], type_hint); + check_expr_base(c, &o, rhs_expr, type_hint); if (o.mode == Addressing_NoValue) { error_operand_no_value(&o); o.mode = Addressing_Invalid; @@ -5022,8 +5013,8 @@ gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array } } else { TypeTuple *tuple = &o.type->Tuple; - for_array(j, tuple->variables) { - o.type = tuple->variables[j]->type; + for (Entity *e : tuple->variables) { + o.type = e->type; array_add(operands, o); } @@ -5115,8 +5106,8 @@ gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize } } else { TypeTuple *tuple = &o.type->Tuple; - for_array(j, tuple->variables) { - o.type = tuple->variables[j]->type; + for (Entity *e : tuple->variables) { + o.type = e->type; array_add(operands, o); } @@ -5459,8 +5450,7 @@ gb_internal CALL_ARGUMENT_CHECKER(check_named_call_arguments) { bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count); auto ordered_operands = array_make(temporary_allocator(), param_count); defer ({ - for_array(i, ordered_operands) { - Operand const &o = ordered_operands[i]; + for (Operand const &o : ordered_operands) { if (o.expr != nullptr) { call->viral_state_flags |= o.expr->viral_state_flags; } @@ -5778,8 +5768,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op param_tuple = &pt->params->Tuple; } if (param_tuple != nullptr) { - for_array(i, param_tuple->variables) { - Entity *e = param_tuple->variables[i]; + for (Entity *e : param_tuple->variables) { if (is_blank_ident(e->token)) { continue; } @@ -5789,8 +5778,8 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op } } else { Array procs = proc_group_entities(c, *operand); - for_array(j, procs) { - Type *proc_type = base_type(procs[j]->type); + for (Entity *proc : procs) { + Type *proc_type = base_type(proc->type); if (is_type_proc(proc_type)) { TypeProc *pt = &proc_type->Proc; TypeTuple *param_tuple = nullptr; @@ -5800,8 +5789,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op if (param_tuple == nullptr) { continue; } - for_array(i, param_tuple->variables) { - Entity *e = param_tuple->variables[i]; + for (Entity *e : param_tuple->variables) { if (is_blank_ident(e->token)) { continue; } @@ -5865,10 +5853,10 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op if (procs.count > 1) { isize max_arg_count = args.count; - for_array(i, args) { + for (Ast *arg : args) { // NOTE(bill): The only thing that may have multiple values // will be a call expression (assuming `or_return` and `()` will be stripped) - Ast *arg = strip_or_return_expr(args[i]); + arg = strip_or_return_expr(arg); if (arg && arg->kind == Ast_CallExpr) { max_arg_count = ISIZE_MAX; break; @@ -5931,8 +5919,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op // where the same positional parameter has the same type value (and ellipsis) bool proc_arg_count_all_equal = true; isize proc_arg_count = -1; - for_array(i, procs) { - Entity *p = procs[i]; + for (Entity *p : procs) { Type *pt = base_type(p->type); if (pt != nullptr && is_type_proc(pt)) { if (proc_arg_count < 0) { @@ -5954,8 +5941,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count); for (isize param_index = 0; param_index < lhs_count; param_index++) { Entity *e = nullptr; - for_array(j, procs) { - Entity *p = procs[j]; + for (Entity *p : procs) { Type *pt = base_type(p->type); if (pt != nullptr && is_type_proc(pt)) { if (e == nullptr) { @@ -5996,8 +5982,8 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op auto proc_entities = array_make(heap_allocator(), 0, procs.count*2 + 1); defer (array_free(&proc_entities)); - for_array(i, procs) { - array_add(&proc_entities, procs[i]); + for (Entity *proc : procs) { + array_add(&proc_entities, proc); } @@ -6087,8 +6073,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op if (procs.count > 0) { error_line("Did you mean to use one of the following:\n"); } - for_array(i, procs) { - Entity *proc = procs[i]; + for (Entity *proc : procs) { TokenPos pos = proc->token.pos; Type *t = base_type(proc->type); if (t == t_invalid) continue; @@ -6647,8 +6632,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (args.count > 0) { bool fail = false; bool first_is_field_value = (args[0]->kind == Ast_FieldValue); - for_array(i, args) { - Ast *arg = args[i]; + for (Ast *arg : args) { bool mix = false; if (first_is_field_value) { mix = arg->kind != Ast_FieldValue; @@ -6669,8 +6653,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } if (operand->mode == Addressing_Invalid) { - for_array(i, args) { - Ast *arg = args[i]; + for (Ast *arg : args) { if (arg->kind == Ast_FieldValue) { arg = arg->FieldValue.value; } @@ -7166,9 +7149,7 @@ gb_internal bool attempt_implicit_selector_expr(CheckerContext *c, Operand *o, A Type *union_type = base_type(th); auto operands = array_make(temporary_allocator(), 0, union_type->Union.variants.count); - for_array(i, union_type->Union.variants) { - Type *vt = union_type->Union.variants[i]; - + for (Type *vt : union_type->Union.variants) { Operand x = {}; if (attempt_implicit_selector_expr(c, &x, ise, vt)) { array_add(&operands, x); @@ -7398,8 +7379,7 @@ gb_internal void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind u } bool found = false; - for_array(j, bt->Enum.fields) { - Entity *f = bt->Enum.fields[j]; + for (Entity *f : bt->Enum.fields) { GB_ASSERT(f->kind == Entity_Constant); i64 fv = exact_value_to_i64(f->Constant.value); @@ -7917,8 +7897,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * if (cl->elems[0]->kind == Ast_FieldValue) { bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count); - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); continue; @@ -8070,8 +8049,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * RangeCache rc = range_cache_make(heap_allocator()); defer (range_cache_destroy(&rc)); - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); continue; @@ -8252,8 +8230,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * { Type *bt = base_type(index_type); GB_ASSERT(bt->kind == Type_Enum); - for_array(i, bt->Enum.fields) { - Entity *f = bt->Enum.fields[i]; + for (Entity *f : bt->Enum.fields) { if (f->kind != Entity_Constant) { continue; } @@ -8288,8 +8265,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * RangeCache rc = range_cache_make(heap_allocator()); defer (range_cache_destroy(&rc)); - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); continue; @@ -8453,8 +8429,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * auto unhandled = array_make(temporary_allocator(), 0, fields.count); - for_array(i, fields) { - Entity *f = fields[i]; + for (Entity *f : fields) { if (f->kind != Entity_Constant) { continue; } @@ -8580,8 +8555,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * bool key_is_typeid = is_type_typeid(t->Map.key); bool value_is_typeid = is_type_typeid(t->Map.value); - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { error(elem, "Only 'field = value' elements are allowed in a map literal"); continue; @@ -8630,8 +8604,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed"); is_constant = false; } else { - for_array(index, cl->elems) { - Ast *elem = cl->elems[index]; + for (Ast *elem : cl->elems) { if (elem->kind == Ast_FieldValue) { error(elem, "'field = value' in a bit_set a literal is not allowed"); continue; @@ -8683,8 +8656,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * BigInt one = {}; big_int_from_u64(&one, 1); - for_array(i, cl->elems) { - Ast *e = cl->elems[i]; + for (Ast *e : cl->elems) { GB_ASSERT(e->kind != Ast_FieldValue); TypeAndValue tav = e->tav; @@ -8783,8 +8755,7 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no if (bsrc->Union.variants.count != 1 && type_hint != nullptr) { bool allowed = false; - for_array(i, bsrc->Union.variants) { - Type *vt = bsrc->Union.variants[i]; + for (Type *vt : bsrc->Union.variants) { if (are_types_identical(vt, type_hint)) { allowed = true; add_type_info_type(c, vt); @@ -8817,8 +8788,7 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no if (is_type_union(src)) { bool ok = false; - for_array(i, bsrc->Union.variants) { - Type *vt = bsrc->Union.variants[i]; + for (Type *vt : bsrc->Union.variants) { if (are_types_identical(vt, dst)) { ok = true; break; @@ -8978,8 +8948,7 @@ gb_internal ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast if (ce->args.count > 0) { bool fail = false; bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); - for_array(i, ce->args) { - Ast *arg = ce->args[i]; + for (Ast *arg : ce->args) { bool mix = false; if (first_is_field_value) { mix = arg->kind != Ast_FieldValue; @@ -9881,12 +9850,9 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) { if (cl->elems.count == 0) { return true; } else { - for_array(i, cl->elems) { - Ast *elem = cl->elems[i]; + for (Ast *elem : cl->elems) { if (elem->tav.mode != Addressing_Constant) { - // if (elem->tav.value.kind != ExactValue_Invalid) { return false; - // } } if (!is_exact_value_zero(elem->tav.value)) { return false; @@ -10366,8 +10332,7 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan bool parens_needed = false; if (pt->results && pt->results->kind == Ast_FieldList) { - for_array(i, pt->results->FieldList.list) { - Ast *field = pt->results->FieldList.list[i]; + for (Ast *field : pt->results->FieldList.list) { ast_node(f, Field, field); if (f->names.count != 0) { parens_needed = true; -- cgit v1.2.3 From c7a704d345e9bda38da18807a1d7cd5bc5accc17 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 15:26:47 +0000 Subject: Use `RwMutex` for the `Scope` --- src/check_decl.cpp | 12 ++++--- src/check_expr.cpp | 4 ++- src/check_stmt.cpp | 5 ++- src/checker.cpp | 21 +++++++----- src/checker.hpp | 2 +- src/thread_pool.cpp | 27 ++++++++------- src/threading.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 29 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 66f16546c..4afde6e51 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -381,8 +381,8 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e if (found_scope == nullptr) { return; } - mutex_lock(&found_scope->mutex); - defer (mutex_unlock(&found_scope->mutex)); + rw_mutex_lock(&found_scope->mutex); + defer (rw_mutex_unlock(&found_scope->mutex)); // IMPORTANT NOTE(bill, 2021-04-10): Overriding behaviour was flawed in that the // original entity was still used check checked, but the checking was only @@ -1478,7 +1478,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de if (t->kind == Type_Struct) { Scope *scope = t->Struct.scope; GB_ASSERT(scope != nullptr); - MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) { + rw_mutex_lock(&scope->mutex); + for (auto const &entry : scope->elements) { Entity *f = entry.value; if (f->kind == Entity_Variable) { Entity *uvar = alloc_entity_using_variable(e, f->token, f->type, nullptr); @@ -1488,6 +1489,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de array_add(&using_entities, puv); } } + rw_mutex_unlock(&scope->mutex); } else { error(e->token, "'using' can only be applied to variables of type struct"); break; @@ -1496,7 +1498,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de } } - MUTEX_GUARD_BLOCK(ctx->scope->mutex) for (auto const &entry : using_entities) { + rw_mutex_lock(&ctx->scope->mutex); + for (auto const &entry : using_entities) { Entity *e = entry.e; Entity *uvar = entry.uvar; Entity *prev = scope_insert_no_mutex(ctx->scope, uvar); @@ -1506,6 +1509,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de break; } } + rw_mutex_unlock(&ctx->scope->mutex); bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c1787e7b6..d9ab328cb 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -236,10 +236,12 @@ gb_internal void check_did_you_mean_scope(String const &name, Scope *scope, char DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.entries.count, name); defer (did_you_mean_destroy(&d)); - MUTEX_GUARD_BLOCK(&scope->mutex) for (auto const &entry : scope->elements) { + rw_mutex_shared_lock(&scope->mutex); + for (auto const &entry : scope->elements) { Entity *e = entry.value; did_you_mean_append(&d, e->token.string); } + rw_mutex_shared_unlock(&scope->mutex); check_did_you_mean_print(&d, prefix); } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index e075297a4..6e84d0789 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -622,7 +622,10 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, case Entity_ImportName: { Scope *scope = e->ImportName.scope; - MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) { + rw_mutex_lock(&scope->mutex); + defer (rw_mutex_unlock(&scope->mutex)); + + for (auto const &entry : scope->elements) { String name = entry.key.string; Entity *decl = entry.value; if (!is_entity_exported(decl)) continue; diff --git a/src/checker.cpp b/src/checker.cpp index 0075fa543..1d536074d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -51,10 +51,11 @@ gb_internal bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *f gb_internal void scope_reset(Scope *scope) { if (scope == nullptr) return; - MUTEX_GUARD(&scope->mutex); + rw_mutex_lock(&scope->mutex); scope->head_child.store(nullptr, std::memory_order_relaxed); string_map_clear(&scope->elements); ptr_set_clear(&scope->imported); + rw_mutex_unlock(&scope->mutex); } gb_internal void scope_reserve(Scope *scope, isize capacity) { @@ -180,9 +181,9 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { gb_zero_item(d); d->parent = parent; d->scope = scope; - ptr_set_init(&d->deps); - ptr_set_init(&d->type_info_deps); - array_init (&d->labels, heap_allocator()); + ptr_set_init(&d->deps, 0); + ptr_set_init(&d->type_info_deps, 0); + d->labels.allocator = heap_allocator(); } gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) { @@ -394,9 +395,9 @@ gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **s StringHashKey key = string_hash_string(name); for (Scope *s = scope; s != nullptr; s = s->parent) { Entity **found = nullptr; - mutex_lock(&s->mutex); + rw_mutex_shared_lock(&s->mutex); found = string_map_get(&s->elements, key); - mutex_unlock(&s->mutex); + rw_mutex_shared_unlock(&s->mutex); if (found) { Entity *e = *found; if (gone_thru_proc) { @@ -482,7 +483,7 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity Entity **found = nullptr; Entity *result = nullptr; - MUTEX_GUARD(&s->mutex); + rw_mutex_lock(&s->mutex); found = string_map_get(&s->elements, key); @@ -509,6 +510,8 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity entity->scope = s; } end:; + rw_mutex_unlock(&s->mutex); + return result; } @@ -669,7 +672,8 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope) { Array vetted_entities = {}; array_init(&vetted_entities, heap_allocator()); - MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) { + rw_mutex_shared_lock(&scope->mutex); + for (auto const &entry : scope->elements) { Entity *e = entry.value; if (e == nullptr) continue; VettedEntity ve_unused = {}; @@ -686,6 +690,7 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope) { array_add(&vetted_entities, ve_shadowed); } } + rw_mutex_shared_unlock(&scope->mutex); gb_sort(vetted_entities.data, vetted_entities.count, gb_size_of(VettedEntity), vetted_entity_variable_pos_cmp); diff --git a/src/checker.hpp b/src/checker.hpp index cc92fce28..53052d5cd 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -224,7 +224,7 @@ struct Scope { std::atomic next; std::atomic head_child; - BlockingMutex mutex; + RwMutex mutex; StringMap elements; PtrSet imported; diff --git a/src/thread_pool.cpp b/src/thread_pool.cpp index 276e93dff..2c369eaad 100644 --- a/src/thread_pool.cpp +++ b/src/thread_pool.cpp @@ -47,7 +47,7 @@ gb_internal void thread_pool_destroy(ThreadPool *pool) { for_array_off(i, 1, pool->threads) { Thread *t = &pool->threads[i]; - pool->tasks_available.fetch_add(1, std::memory_order_release); + pool->tasks_available.fetch_add(1, std::memory_order_relaxed); futex_broadcast(&pool->tasks_available); thread_join_and_destroy(t); } @@ -74,7 +74,7 @@ void thread_pool_queue_push(Thread *thread, WorkerTask task) { } while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture)); thread->pool->tasks_left.fetch_add(1, std::memory_order_release); - thread->pool->tasks_available.fetch_add(1, std::memory_order_release); + thread->pool->tasks_available.fetch_add(1, std::memory_order_relaxed); futex_broadcast(&thread->pool->tasks_available); } @@ -82,7 +82,7 @@ bool thread_pool_queue_pop(Thread *thread, WorkerTask *task) { u64 capture; u64 new_capture; do { - capture = thread->head_and_tail.load(); + capture = thread->head_and_tail.load(std::memory_order_acquire); u64 mask = thread->capacity - 1; u64 head = (capture >> 32) & mask; @@ -97,7 +97,7 @@ bool thread_pool_queue_pop(Thread *thread, WorkerTask *task) { *task = thread->queue[tail]; new_capture = (head << 32) | new_tail; - } while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture)); + } while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture, std::memory_order_release)); return true; } @@ -168,22 +168,21 @@ gb_internal THREAD_PROC(thread_pool_thread_proc) { Thread *thread = &pool->threads.data[idx]; WorkerTask task; - if (!thread_pool_queue_pop(thread, &task)) { - continue; - } - task.do_work(task.data); - pool->tasks_left.fetch_sub(1, std::memory_order_release); + if (thread_pool_queue_pop(thread, &task)) { + task.do_work(task.data); + pool->tasks_left.fetch_sub(1, std::memory_order_release); - if (pool->tasks_left.load(std::memory_order_acquire) == 0) { - futex_signal(&pool->tasks_left); - } + if (pool->tasks_left.load(std::memory_order_acquire) == 0) { + futex_signal(&pool->tasks_left); + } - goto main_loop_continue; + goto main_loop_continue; + } } } // if we've done all our work, and there's nothing to steal, go to sleep - state = pool->tasks_available.load(); + state = pool->tasks_available.load(std::memory_order_acquire); futex_wait(&pool->tasks_available, state); main_loop_continue:; diff --git a/src/threading.cpp b/src/threading.cpp index 78943150e..27a17112e 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -8,10 +8,12 @@ struct BlockingMutex; struct RecursiveMutex; +struct RwMutex; struct Semaphore; struct Condition; struct Thread; struct ThreadPool; +struct Parker; #define THREAD_PROC(name) isize name(struct Thread *thread) gb_internal THREAD_PROC(thread_pool_thread_proc); @@ -56,6 +58,13 @@ gb_internal void mutex_lock (RecursiveMutex *m); gb_internal bool mutex_try_lock(RecursiveMutex *m); gb_internal void mutex_unlock (RecursiveMutex *m); +gb_internal void rw_mutex_lock (RwMutex *m); +gb_internal bool rw_mutex_try_lock (RwMutex *m); +gb_internal void rw_mutex_unlock (RwMutex *m); +gb_internal void rw_mutex_shared_lock (RwMutex *m); +gb_internal bool rw_mutex_try_shared_lock(RwMutex *m); +gb_internal void rw_mutex_shared_unlock (RwMutex *m); + gb_internal void semaphore_post (Semaphore *s, i32 count); gb_internal void semaphore_wait (Semaphore *s); gb_internal void semaphore_release(Semaphore *s) { semaphore_post(s, 1); } @@ -65,6 +74,10 @@ gb_internal void condition_broadcast(Condition *c); gb_internal void condition_signal(Condition *c); gb_internal void condition_wait(Condition *c, BlockingMutex *m); +gb_internal void park(Parker *p); +gb_internal void unpark_one(Parker *p); +gb_internal void unpark_all(Parker *p); + gb_internal u32 thread_current_id(void); gb_internal void thread_init (ThreadPool *pool, Thread *t, isize idx); @@ -205,6 +218,30 @@ gb_internal void semaphore_wait(Semaphore *s) { gb_internal void condition_wait(Condition *c, BlockingMutex *m) { SleepConditionVariableSRW(&c->cond, &m->srwlock, INFINITE, 0); } + + struct RwMutex { + SRWLOCK srwlock; + }; + + gb_internal void rw_mutex_lock(RwMutex *m) { + AcquireSRWLockExclusive(&m->srwlock); + } + gb_internal bool rw_mutex_try_lock(RwMutex *m) { + return !!TryAcquireSRWLockExclusive(&m->srwlock); + } + gb_internal void rw_mutex_unlock(RwMutex *m) { + ReleaseSRWLockExclusive(&m->srwlock); + } + + gb_internal void rw_mutex_shared_lock(RwMutex *m) { + AcquireSRWLockShared(&m->srwlock); + } + gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) { + return !!TryAcquireSRWLockShared(&m->srwlock); + } + gb_internal void rw_mutex_shared_unlock(RwMutex *m) { + ReleaseSRWLockShared(&m->srwlock); + } #else enum Internal_Mutex_State : i32 { Internal_Mutex_State_Unlocked = 0, @@ -306,8 +343,67 @@ gb_internal void semaphore_wait(Semaphore *s) { futex_wait(&c->state(), state); mutex_lock(m); } + + struct RwMutex { + // TODO(bill): make this a proper RW mutex + BlockingMutex mutex; + }; + + gb_internal void rw_mutex_lock(RwMutex *m) { + mutex_lock(&m->mutex); + } + gb_internal bool rw_mutex_try_lock(RwMutex *m) { + return mutex_try_lock(&m->mutex); + } + gb_internal void rw_mutex_unlock(RwMutex *m) { + mutex_unlock(&m->mutex); + } + + gb_internal void rw_mutex_shared_lock(RwMutex *m) { + mutex_lock(&m->mutex); + } + gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) { + return mutex_try_lock(&m->mutex); + } + gb_internal void rw_mutex_shared_unlock(RwMutex *m) { + mutex_unlock(&m->mutex); + } #endif +struct Parker { + Futex state; +}; +enum ParkerState : u32 { + ParkerState_Empty = 0, + ParkerState_Notified = 1, + ParkerState_Parked = UINT32_MAX, +}; + +gb_internal void park(Parker *p) { + if (p->state.fetch_sub(1, std::memory_order_acquire) == ParkerState_Notified) { + return; + } + for (;;) { + futex_wait(&p->state, ParkerState_Parked); + i32 notified = ParkerState_Empty; + if (p->state.compare_exchange_strong(notified, ParkerState_Empty, std::memory_order_acquire, std::memory_order_acquire)) { + return; + } + } +} + +gb_internal void unpark_one(Parker *p) { + if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) { + futex_signal(&p->state); + } +} + +gb_internal void unpark_all(Parker *p) { + if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) { + futex_broadcast(&p->state); + } +} + gb_internal u32 thread_current_id(void) { u32 thread_id; -- cgit v1.2.3 From 3dee3205b299b2a2e803a3bc248f0a9ffdcce69e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 15:34:52 +0000 Subject: Use `RwMutex` for `DeclInfo` `deps --- src/check_decl.cpp | 27 +++++++++++++++++---------- src/check_expr.cpp | 6 ++++-- src/checker.cpp | 8 ++++---- src/checker.hpp | 4 ++-- 4 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 4afde6e51..72c69b5dc 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1584,19 +1584,26 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de // NOTE(bill): Add the dependencies from the procedure literal (lambda) // But only at the procedure level - MUTEX_GUARD_BLOCK(decl->deps_mutex) - MUTEX_GUARD_BLOCK(decl->parent->deps_mutex) { - for (Entity *e : decl->deps) { - ptr_set_add(&decl->parent->deps, e); - } + rw_mutex_shared_lock(&decl->deps_mutex); + rw_mutex_lock(&decl->parent->deps_mutex); + + for (Entity *e : decl->deps) { + ptr_set_add(&decl->parent->deps, e); } - MUTEX_GUARD_BLOCK(decl->type_info_deps_mutex) - MUTEX_GUARD_BLOCK(decl->parent->type_info_deps_mutex) { - for (Type *t : decl->type_info_deps) { - ptr_set_add(&decl->parent->type_info_deps, t); - } + rw_mutex_unlock(&decl->parent->deps_mutex); + rw_mutex_shared_unlock(&decl->deps_mutex); + + + rw_mutex_shared_lock(&decl->type_info_deps_mutex); + rw_mutex_lock(&decl->parent->type_info_deps_mutex); + + for (Type *t : decl->type_info_deps) { + ptr_set_add(&decl->parent->type_info_deps, t); } + + rw_mutex_unlock(&decl->parent->type_info_deps_mutex); + rw_mutex_shared_unlock(&decl->type_info_deps_mutex); } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d9ab328cb..e3cd66db6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4928,21 +4928,23 @@ gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = fals gb_internal isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) { if (lhs != nullptr && c->decl != nullptr) { - mutex_lock(&c->info->deps_mutex); + // mutex_lock(&c->info->deps_mutex); for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) { Entity *e = lhs[tuple_index + j]; if (e != nullptr) { DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { + rw_mutex_lock(&c->decl->deps_mutex); for (Entity *dep : decl->deps) { ptr_set_add(&c->decl->deps, dep); } + rw_mutex_unlock(&c->decl->deps_mutex); } } } - mutex_unlock(&c->info->deps_mutex); + // mutex_unlock(&c->info->deps_mutex); } return tuple_count; } diff --git a/src/checker.cpp b/src/checker.cpp index 1d536074d..fd80d07de 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -744,17 +744,17 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope) { gb_internal void add_dependency(CheckerInfo *info, DeclInfo *d, Entity *e) { - mutex_lock(&d->deps_mutex); + rw_mutex_lock(&d->deps_mutex); ptr_set_add(&d->deps, e); - mutex_unlock(&d->deps_mutex); + rw_mutex_unlock(&d->deps_mutex); } gb_internal void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type *type) { if (d == nullptr) { return; } - mutex_lock(&d->type_info_deps_mutex); + rw_mutex_lock(&d->type_info_deps_mutex); ptr_set_add(&d->type_info_deps, type); - mutex_unlock(&d->type_info_deps_mutex); + rw_mutex_unlock(&d->type_info_deps_mutex); } gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) { diff --git a/src/checker.hpp b/src/checker.hpp index 53052d5cd..50f4a204c 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -179,10 +179,10 @@ struct DeclInfo { CommentGroup *comment; CommentGroup *docs; - BlockingMutex deps_mutex; + RwMutex deps_mutex; PtrSet deps; - BlockingMutex type_info_deps_mutex; + RwMutex type_info_deps_mutex; PtrSet type_info_deps; Array labels; -- cgit v1.2.3 From 485c6066724b374de5b94115411f529493f799f7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 15:37:35 +0000 Subject: Clarify `RwLock`s for `add_dependenies_from_unpacking` --- src/check_expr.cpp | 6 ++---- src/checker.hpp | 6 ------ 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e3cd66db6..38fe33c24 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4928,23 +4928,21 @@ gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = fals gb_internal isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) { if (lhs != nullptr && c->decl != nullptr) { - // mutex_lock(&c->info->deps_mutex); - for (isize j = 0; (tuple_index + j) < lhs_count && j < tuple_count; j++) { Entity *e = lhs[tuple_index + j]; if (e != nullptr) { DeclInfo *decl = decl_info_of_entity(e); if (decl != nullptr) { + rw_mutex_shared_lock(&decl->deps_mutex); rw_mutex_lock(&c->decl->deps_mutex); for (Entity *dep : decl->deps) { ptr_set_add(&c->decl->deps, dep); } rw_mutex_unlock(&c->decl->deps_mutex); + rw_mutex_shared_unlock(&decl->deps_mutex); } } } - - // mutex_unlock(&c->info->deps_mutex); } return tuple_count; } diff --git a/src/checker.hpp b/src/checker.hpp index 50f4a204c..554c8ddf4 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -357,12 +357,6 @@ struct CheckerInfo { BlockingMutex global_untyped_mutex; BlockingMutex builtin_mutex; - // NOT recursive & only used at the end of `check_proc_body` - // and in `add_dependency`. - // This is a possible source of contention but probably not - // too much of a problem in practice - BlockingMutex deps_mutex; - BlockingMutex type_and_value_mutex; RecursiveMutex lazy_mutex; // Mutex required for lazy type checking of specific files -- cgit v1.2.3 From 774fea1e63941473b9899a50585e0f171184a147 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 15:47:25 +0000 Subject: Use `RwMutex` for `gen_procs` --- src/check_expr.cpp | 16 ++++++++-------- src/checker.cpp | 13 +++++++------ src/checker.hpp | 11 +++-------- src/llvm_backend_stmt.cpp | 3 ++- 4 files changed, 20 insertions(+), 23 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 38fe33c24..746a29ce0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -440,11 +440,11 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E auto *found = map_get(&info->gen_procs, base_entity->identifier.load()); if (found) { gen_procs = *found; - mutex_lock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_lock(&gen_procs->mutex); // @local-mutex for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { - mutex_unlock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex // @@GPM //////////////////////////// mutex_unlock(&info->gen_procs_mutex); ///////////////////////////////////// @@ -455,7 +455,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } - mutex_unlock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex } else { gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); gen_procs->procs.allocator = heap_allocator(); @@ -481,11 +481,11 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return false; } - mutex_lock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_lock(&gen_procs->mutex); // @local-mutex for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { - mutex_unlock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex if (poly_proc_data) { poly_proc_data->gen_entity = other; @@ -509,7 +509,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } - mutex_unlock(&gen_procs->mutex); // @local-mutex + rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex } @@ -569,9 +569,9 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E } } - mutex_lock(&gen_procs->mutex); // @local-mutex + rw_mutex_lock(&gen_procs->mutex); // @local-mutex array_add(&gen_procs->procs, entity); - mutex_unlock(&gen_procs->mutex); // @local-mutex + rw_mutex_unlock(&gen_procs->mutex); // @local-mutex ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); proc_info->file = file; diff --git a/src/checker.cpp b/src/checker.cpp index fd80d07de..3f5c2892f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1356,9 +1356,9 @@ gb_internal ExprInfo *check_get_expr_info(CheckerContext *c, Ast *expr) { } return nullptr; } else { - mutex_lock(&c->info->global_untyped_mutex); - defer (mutex_unlock(&c->info->global_untyped_mutex)); + rw_mutex_shared_lock(&c->info->global_untyped_mutex); ExprInfo **found = map_get(&c->info->global_untyped, expr); + rw_mutex_shared_unlock(&c->info->global_untyped_mutex); if (found) { return *found; } @@ -1370,9 +1370,9 @@ gb_internal void check_set_expr_info(CheckerContext *c, Ast *expr, AddressingMod if (c->untyped != nullptr) { map_set(c->untyped, expr, make_expr_info(mode, type, value, false)); } else { - mutex_lock(&c->info->global_untyped_mutex); + rw_mutex_lock(&c->info->global_untyped_mutex); map_set(&c->info->global_untyped, expr, make_expr_info(mode, type, value, false)); - mutex_unlock(&c->info->global_untyped_mutex); + rw_mutex_unlock(&c->info->global_untyped_mutex); } } @@ -1382,10 +1382,10 @@ gb_internal void check_remove_expr_info(CheckerContext *c, Ast *e) { GB_ASSERT(map_get(c->untyped, e) == nullptr); } else { auto *untyped = &c->info->global_untyped; - mutex_lock(&c->info->global_untyped_mutex); + rw_mutex_lock(&c->info->global_untyped_mutex); map_remove(untyped, e); GB_ASSERT(map_get(untyped, e) == nullptr); - mutex_unlock(&c->info->global_untyped_mutex); + rw_mutex_unlock(&c->info->global_untyped_mutex); } } @@ -1454,6 +1454,7 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo BlockingMutex *mutex = &ctx->info->type_and_value_mutex; if (ctx->pkg) { + // TODO(bill): is a per package mutex is a good idea here? mutex = &ctx->pkg->type_and_value_mutex; } diff --git a/src/checker.hpp b/src/checker.hpp index 554c8ddf4..226f69c1c 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -317,7 +317,7 @@ struct LoadFileCache { struct GenProcsData { Array procs; - BlockingMutex mutex; + RwMutex mutex; }; // CheckerInfo stores all the symbol information for a type-checked program @@ -347,14 +347,9 @@ struct CheckerInfo { // Below are accessed within procedures - // NOTE(bill): If the semantic checker (check_proc_body) is to ever to be multithreaded, - // these variables will be of contention - - Semaphore collect_semaphore; - + RwMutex global_untyped_mutex; UntypedExprInfoMap global_untyped; // NOTE(bill): This needs to be a map and not on the Ast // as it needs to be iterated across afterwards - BlockingMutex global_untyped_mutex; BlockingMutex builtin_mutex; BlockingMutex type_and_value_mutex; @@ -388,7 +383,7 @@ struct CheckerInfo { BlockingMutex load_file_mutex; StringMap load_file_cache; - BlockingMutex all_procedures_mutex;; + BlockingMutex all_procedures_mutex; Array all_procedures; }; diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index c48115079..1660d3487 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -57,7 +57,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) auto *found = map_get(&info->gen_procs, ident); if (found) { GenProcsData *gpd = *found; - MUTEX_GUARD(&gpd->mutex); + rw_mutex_shared_lock(&gpd->mutex); for (Entity *e : gpd->procs) { if (!ptr_set_exists(min_dep_set, e)) { continue; @@ -65,6 +65,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) DeclInfo *d = decl_info_of_entity(e); lb_build_nested_proc(p, &d->proc_lit->ProcLit, e); } + rw_mutex_shared_unlock(&gpd->mutex); } else { lb_build_nested_proc(p, pl, e); } -- cgit v1.2.3 From 855ebceadcc4612a6451f268ab6d6693838ed5f4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 17:26:05 +0000 Subject: Minimize `add_type_info_type` usage --- src/check_builtin.cpp | 2 +- src/check_expr.cpp | 8 ++++---- src/check_stmt.cpp | 8 +++++--- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 7c5521dde..606283c32 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3573,7 +3573,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); add_entity(c, scope, nullptr, base_type_entity); - add_type_info_type(c, soa_struct); + // add_type_info_type(c, soa_struct); operand->type = soa_struct; break; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 746a29ce0..5f28504a2 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8779,8 +8779,8 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no return kind; } - add_type_info_type(c, o->type); - add_type_info_type(c, bsrc->Union.variants[0]); + // add_type_info_type(c, o->type); + // add_type_info_type(c, bsrc->Union.variants[0]); o->type = bsrc->Union.variants[0]; o->mode = Addressing_OptionalOk; @@ -8812,8 +8812,8 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no return kind; } - add_type_info_type(c, o->type); - add_type_info_type(c, t); + // add_type_info_type(c, o->type); + // add_type_info_type(c, t); o->type = t; o->mode = Addressing_OptionalOk; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 6e84d0789..9547035d0 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1132,7 +1132,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ check_expr(ctx, &x, rhs); check_assignment(ctx, &x, nullptr, str_lit("type switch expression")); - add_type_info_type(ctx, x.type); + // add_type_info_type(ctx, x.type); TypeSwitchKind switch_kind = check_valid_type_switch_type(x.type); if (switch_kind == TypeSwitch_Invalid) { @@ -1223,7 +1223,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ continue; } case_type = y.type; - add_type_info_type(ctx, y.type); + // add_type_info_type(ctx, y.type); } else if (switch_kind == TypeSwitch_Any) { case_type = y.type; add_type_info_type(ctx, y.type); @@ -1259,7 +1259,9 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ if (case_type == nullptr) { case_type = x.type; } - add_type_info_type(ctx, case_type); + if (switch_kind == TypeSwitch_Any) { + add_type_info_type(ctx, case_type); + } check_open_scope(ctx, stmt); { -- cgit v1.2.3 From 12e42d92d30b3a9cf4d7bb7bb17a2e031285073b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 4 Jan 2023 15:35:24 +0000 Subject: Localize `GenProcsData` to the entity itself --- src/check_expr.cpp | 29 ++++++++++++++--------------- src/checker.cpp | 4 ++-- src/checker.hpp | 2 -- src/entity.cpp | 5 ++++- src/llvm_backend_stmt.cpp | 6 ++---- 5 files changed, 22 insertions(+), 24 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 5f28504a2..bce16f304 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -366,8 +366,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E GB_ASSERT(dst == nullptr); } - // MUTEX_GUARD(&info->gen_procs_mutex); - if (!src->Proc.is_polymorphic || src->Proc.is_poly_specialized) { return false; } @@ -434,20 +432,21 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E GenProcsData *gen_procs = nullptr; - // @@GPM ////////////////////////// - mutex_lock(&info->gen_procs_mutex); - /////////////////////////////////// - auto *found = map_get(&info->gen_procs, base_entity->identifier.load()); - if (found) { - gen_procs = *found; + GB_ASSERT(base_entity->identifier.load()->kind == Ast_Ident); + GB_ASSERT(base_entity->kind == Entity_Procedure); + + + mutex_lock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex + + gen_procs = base_entity->Procedure.gen_procs; + if (gen_procs) { rw_mutex_shared_lock(&gen_procs->mutex); // @local-mutex + for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex - // @@GPM //////////////////////////// - mutex_unlock(&info->gen_procs_mutex); - ///////////////////////////////////// + mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex if (poly_proc_data) { poly_proc_data->gen_entity = other; @@ -455,15 +454,15 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E return true; } } + rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex } else { gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); gen_procs->procs.allocator = heap_allocator(); - map_set(&info->gen_procs, base_entity->identifier.load(), gen_procs); + base_entity->Procedure.gen_procs = gen_procs; } - // @@GPM //////////////////////////// - mutex_unlock(&info->gen_procs_mutex); - ///////////////////////////////////// + + mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex { // LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice diff --git a/src/checker.cpp b/src/checker.cpp index 5fc9a5551..0bebce232 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1143,7 +1143,7 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->entities, a); map_init(&i->global_untyped); string_map_init(&i->foreigns); - map_init(&i->gen_procs); + // map_init(&i->gen_procs); map_init(&i->gen_types); array_init(&i->type_info_types, a); map_init(&i->type_info_map); @@ -1172,7 +1172,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { array_free(&i->entities); map_destroy(&i->global_untyped); string_map_destroy(&i->foreigns); - map_destroy(&i->gen_procs); + // map_destroy(&i->gen_procs); map_destroy(&i->gen_types); array_free(&i->type_info_types); map_destroy(&i->type_info_map); diff --git a/src/checker.hpp b/src/checker.hpp index 92926689e..8b8819d97 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -368,9 +368,7 @@ struct CheckerInfo { RecursiveMutex lazy_mutex; // Mutex required for lazy type checking of specific files - BlockingMutex gen_procs_mutex; RwMutex gen_types_mutex; - PtrMap gen_procs; // Key: Ast * | Identifier -> Entity PtrMap gen_types; BlockingMutex type_info_mutex; // NOT recursive diff --git a/src/entity.cpp b/src/entity.cpp index f82a2fb05..b92ba825f 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -130,7 +130,7 @@ enum EntityConstantFlags : u32 { EntityConstantFlag_ImplicitEnumValue = 1<<0, }; -enum ProcedureOptimizationMode : u32 { +enum ProcedureOptimizationMode : u8 { ProcedureOptimizationMode_Default, ProcedureOptimizationMode_None, ProcedureOptimizationMode_Minimal, @@ -233,6 +233,9 @@ struct Entity { String link_name; String link_prefix; DeferredProcedure deferred_procedure; + + struct GenProcsData *gen_procs; + BlockingMutex gen_procs_mutex; ProcedureOptimizationMode optimization_mode; bool is_foreign : 1; bool is_export : 1; diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 1660d3487..0e6f75118 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -50,13 +50,11 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) continue; // It's an alias } - CheckerInfo *info = p->module->info; DeclInfo *decl = decl_info_of_entity(e); ast_node(pl, ProcLit, decl->proc_lit); if (pl->body != nullptr) { - auto *found = map_get(&info->gen_procs, ident); - if (found) { - GenProcsData *gpd = *found; + GenProcsData *gpd = e->Procedure.gen_procs; + if (gpd) { rw_mutex_shared_lock(&gpd->mutex); for (Entity *e : gpd->procs) { if (!ptr_set_exists(min_dep_set, e)) { -- cgit v1.2.3 From 8a99b8af3e875141156d359026b785fcfd284f57 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 4 Jan 2023 15:55:10 +0000 Subject: Narrow mutex usage --- src/check_expr.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index bce16f304..e9e61486e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -435,18 +435,17 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E GB_ASSERT(base_entity->identifier.load()->kind == Ast_Ident); GB_ASSERT(base_entity->kind == Entity_Procedure); - mutex_lock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex - gen_procs = base_entity->Procedure.gen_procs; if (gen_procs) { rw_mutex_shared_lock(&gen_procs->mutex); // @local-mutex + mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex + for (Entity *other : gen_procs->procs) { Type *pt = base_type(other->type); if (are_types_identical(pt, final_proc_type)) { rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex - mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex if (poly_proc_data) { poly_proc_data->gen_entity = other; @@ -460,9 +459,9 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); gen_procs->procs.allocator = heap_allocator(); base_entity->Procedure.gen_procs = gen_procs; + mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex } - mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex { // LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice -- cgit v1.2.3 From 1517f1d7793c8985664600a820e3434dfdf83810 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 5 Jan 2023 11:54:21 +0000 Subject: Add uncomment `add_type_info_type` calls for type assertions --- src/check_decl.cpp | 60 ++++++++++++++++++++++++++++------------------------ src/check_expr.cpp | 8 +++---- src/checker.cpp | 38 +++++---------------------------- src/llvm_backend.cpp | 1 + src/ptr_map.cpp | 29 +++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 65 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 644771dcd..d4ae9c59d 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1411,6 +1411,37 @@ end:; } +gb_internal void add_deps_from_child_to_parent(DeclInfo *decl) { + if (decl && decl->parent) { + Scope *ps = decl->parent->scope; + if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) { + return; + } else { + // NOTE(bill): Add the dependencies from the procedure literal (lambda) + // But only at the procedure level + rw_mutex_shared_lock(&decl->deps_mutex); + rw_mutex_lock(&decl->parent->deps_mutex); + + for (Entity *e : decl->deps) { + ptr_set_add(&decl->parent->deps, e); + } + + rw_mutex_unlock(&decl->parent->deps_mutex); + rw_mutex_shared_unlock(&decl->deps_mutex); + + rw_mutex_shared_lock(&decl->type_info_deps_mutex); + rw_mutex_lock(&decl->parent->type_info_deps_mutex); + + for (Type *t : decl->type_info_deps) { + ptr_set_add(&decl->parent->type_info_deps, t); + } + + rw_mutex_unlock(&decl->parent->type_info_deps_mutex); + rw_mutex_shared_unlock(&decl->type_info_deps_mutex); + } + } +} + struct ProcUsingVar { Entity *e; Entity *uvar; @@ -1576,34 +1607,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de check_scope_usage(ctx->checker, ctx->scope); - // if (decl->parent) { - // Scope *ps = decl->parent->scope; - // if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) { - // return true; - // } else { - // // NOTE(bill): Add the dependencies from the procedure literal (lambda) - // // But only at the procedure level - // rw_mutex_shared_lock(&decl->deps_mutex); - // rw_mutex_lock(&decl->parent->deps_mutex); - - // for (Entity *e : decl->deps) { - // ptr_set_add(&decl->parent->deps, e); - // } - - // rw_mutex_unlock(&decl->parent->deps_mutex); - // rw_mutex_shared_unlock(&decl->deps_mutex); - - // rw_mutex_shared_lock(&decl->type_info_deps_mutex); - // rw_mutex_lock(&decl->parent->type_info_deps_mutex); - - // for (Type *t : decl->type_info_deps) { - // ptr_set_add(&decl->parent->type_info_deps, t); - // } - - // rw_mutex_unlock(&decl->parent->type_info_deps_mutex); - // rw_mutex_shared_unlock(&decl->type_info_deps_mutex); - // } - // } + add_deps_from_child_to_parent(decl); return true; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e9e61486e..e0519d26b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8777,8 +8777,8 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no return kind; } - // add_type_info_type(c, o->type); - // add_type_info_type(c, bsrc->Union.variants[0]); + add_type_info_type(c, o->type); + add_type_info_type(c, bsrc->Union.variants[0]); o->type = bsrc->Union.variants[0]; o->mode = Addressing_OptionalOk; @@ -8810,8 +8810,8 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no return kind; } - // add_type_info_type(c, o->type); - // add_type_info_type(c, t); + add_type_info_type(c, o->type); + add_type_info_type(c, t); o->type = t; o->mode = Addressing_OptionalOk; diff --git a/src/checker.cpp b/src/checker.cpp index 8cb6ea99d..a2ed73119 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2026,14 +2026,13 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { ti_index = type_info_index(&c->info, t, false); } GB_ASSERT(ti_index >= 0); - if (map_get(set, ti_index)) { - // Type already exists; - return; - } // IMPORTANT NOTE(bill): this must be copied as `map_set` takes a const ref // and effectively assigns the `+1` of the value isize const count = set->entries.count; - map_set(set, ti_index, count); + if (map_set_if_not_previously_exists(set, ti_index, count)) { + // Type already exists; + return; + } // Add nested types if (t->kind == Type_Named) { @@ -5650,34 +5649,7 @@ gb_internal void check_walk_all_dependencies(DeclInfo *decl) { for (DeclInfo *child = decl->next_child; child != nullptr; child = child->next_sibling) { check_walk_all_dependencies(child); } - if (decl->parent && decl->parent->entity && decl->parent->entity->kind == Entity_Procedure) { - Scope *ps = decl->parent->scope; - if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) { - return; - } else { - // NOTE(bill): Add the dependencies from the procedure literal (lambda) - // But only at the procedure level - rw_mutex_shared_lock(&decl->deps_mutex); - rw_mutex_lock(&decl->parent->deps_mutex); - - for (Entity *e : decl->deps) { - ptr_set_add(&decl->parent->deps, e); - } - - rw_mutex_unlock(&decl->parent->deps_mutex); - rw_mutex_shared_unlock(&decl->deps_mutex); - - rw_mutex_shared_lock(&decl->type_info_deps_mutex); - rw_mutex_lock(&decl->parent->type_info_deps_mutex); - - for (Type *t : decl->type_info_deps) { - ptr_set_add(&decl->parent->type_info_deps, t); - } - - rw_mutex_unlock(&decl->parent->type_info_deps_mutex); - rw_mutex_shared_unlock(&decl->type_info_deps_mutex); - } - } + add_deps_from_child_to_parent(decl); } gb_internal void check_update_dependency_tree_for_procedures(Checker *c) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 304e5ef36..192e5cc56 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1920,6 +1920,7 @@ gb_internal void lb_generate_code(lbGenerator *gen) { if (!ptr_set_exists(min_dep_set, e)) { continue; } + DeclInfo *decl = decl_info_of_entity(e); if (decl == nullptr) { continue; diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index c33bf9ffb..89d2cbf9d 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -52,6 +52,7 @@ template gb_internal void map_init (PtrMap< template gb_internal void map_destroy (PtrMap *h); template gb_internal V * map_get (PtrMap *h, K key); template gb_internal void map_set (PtrMap *h, K key, V const &value); +template gb_internal bool map_set_if_not_previously_exists(PtrMap *h, K key, V const &value); // returns true if it previously existed template gb_internal void map_remove (PtrMap *h, K key); template gb_internal void map_clear (PtrMap *h); template gb_internal void map_grow (PtrMap *h); @@ -240,6 +241,34 @@ gb_internal void map_set(PtrMap *h, K key, V const &value) { } } +// returns true if it previously existed +template +gb_internal bool map_set_if_not_previously_exists(PtrMap *h, K key, V const &value) { + MapIndex index; + MapFindResult fr; + if (h->hashes.count == 0) { + map_grow(h); + } + fr = map__find(h, key); + if (fr.entry_index != MAP_SENTINEL) { + return true; + } else { + index = map__add_entry(h, key); + if (fr.entry_prev != MAP_SENTINEL) { + h->entries.data[fr.entry_prev].next = index; + } else { + h->hashes.data[fr.hash_index] = index; + } + } + h->entries.data[index].value = value; + + if (map__full(h)) { + map_grow(h); + } + return false; +} + + template gb_internal void map__erase(PtrMap *h, MapFindResult const &fr) { MapFindResult last; -- cgit v1.2.3