Browse Source

Remove use of queues for procedure checking.

gingerBill 2 years ago
parent
commit
015fe924b8
5 changed files with 52 additions and 78 deletions
  1. 1 1
      src/check_decl.cpp
  2. 4 6
      src/check_expr.cpp
  3. 42 66
      src/checker.cpp
  4. 1 5
      src/checker.hpp
  5. 4 0
      src/thread_pool.cpp

+ 1 - 1
src/check_decl.cpp

@@ -986,7 +986,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 
 
 		GB_ASSERT(pl->body->kind == Ast_BlockStmt);
 		GB_ASSERT(pl->body->kind == Ast_BlockStmt);
 		if (!pt->is_polymorphic) {
 		if (!pt->is_polymorphic) {
-			check_procedure_later(ctx, ctx->file, e->token, d, proc_type, pl->body, pl->tags);
+			check_procedure_later(ctx->checker, ctx->file, e->token, d, proc_type, pl->body, pl->tags);
 		}
 		}
 	} else if (!is_foreign) {
 	} else if (!is_foreign) {
 		if (e->Procedure.is_export) {
 		if (e->Procedure.is_export) {

+ 4 - 6
src/check_expr.cpp

@@ -417,8 +417,6 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E
 
 
 	CheckerContext nctx = *old_c;
 	CheckerContext nctx = *old_c;
 
 
-	nctx.procs_to_check_queue = old_c->procs_to_check_queue;
-
 	Scope *scope = create_scope(info, base_entity->scope);
 	Scope *scope = create_scope(info, base_entity->scope);
 	scope->flags |= ScopeFlag_Proc;
 	scope->flags |= ScopeFlag_Proc;
 	nctx.scope = scope;
 	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
 	// NOTE(bill): Check the newly generated procedure body
-	check_procedure_later(&nctx, proc_info);
+	check_procedure_later(nctx.checker, proc_info);
 
 
 	return true;
 	return true;
 }
 }
@@ -6187,7 +6185,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
 				decl->where_clauses_evaluated = true;
 				decl->where_clauses_evaluated = true;
 
 
 				if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) {
 				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;
 			return data;
@@ -6225,7 +6223,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
 			decl->where_clauses_evaluated = true;
 			decl->where_clauses_evaluated = true;
 
 
 			if (ok && (data.gen_entity->flags & EntityFlag_ProcBodyChecked) == 0) {
 			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;
 		return data;
@@ -9447,7 +9445,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
 			}
 			}
 
 
 			pl->decl = decl;
 			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);
 		check_close_scope(&ctx);
 
 

+ 42 - 66
src/checker.cpp

@@ -1195,7 +1195,6 @@ gb_internal void reset_checker_context(CheckerContext *ctx, AstFile *file, Untyp
 	GB_ASSERT(ctx->checker != nullptr);
 	GB_ASSERT(ctx->checker != nullptr);
 	mutex_lock(&ctx->mutex);
 	mutex_lock(&ctx->mutex);
 
 
-	auto *queue = ctx->procs_to_check_queue;
 	auto type_path = ctx->type_path;
 	auto type_path = ctx->type_path;
 	array_clear(type_path);
 	array_clear(type_path);
 
 
@@ -1211,7 +1210,6 @@ gb_internal void reset_checker_context(CheckerContext *ctx, AstFile *file, Untyp
 
 
 	add_curr_ast_file(ctx, file);
 	add_curr_ast_file(ctx, file);
 
 
-	ctx->procs_to_check_queue = queue;
 	ctx->untyped = untyped;
 	ctx->untyped = untyped;
 
 
 	mutex_unlock(&ctx->mutex);
 	mutex_unlock(&ctx->mutex);
@@ -1232,7 +1230,7 @@ gb_internal void init_checker(Checker *c) {
 	mpmc_init(&c->procs_with_deferred_to_check, a, 1<<10);
 	mpmc_init(&c->procs_with_deferred_to_check, a, 1<<10);
 
 
 	// NOTE(bill): 1 Mi elements should be enough on average
 	// NOTE(bill): 1 Mi elements should be enough on average
-	mpmc_init(&c->procs_to_check_queue, heap_allocator(), 1<<20);
+	array_init(&c->procs_to_check, heap_allocator(), 0, 1<<20);
 
 
 	mpmc_init(&c->global_untyped_queue, a, 1<<20);
 	mpmc_init(&c->global_untyped_queue, a, 1<<20);
 
 
@@ -1244,7 +1242,7 @@ gb_internal void destroy_checker(Checker *c) {
 
 
 	destroy_checker_context(&c->builtin_ctx);
 	destroy_checker_context(&c->builtin_ctx);
 
 
-	mpmc_destroy(&c->procs_to_check_queue);
+	array_free(&c->procs_to_check);
 	mpmc_destroy(&c->global_untyped_queue);
 	mpmc_destroy(&c->global_untyped_queue);
 }
 }
 
 
@@ -1941,23 +1939,19 @@ gb_global std::atomic<bool> global_procedure_body_in_worker_queue = false;
 
 
 gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc);
 gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc);
 
 
-gb_internal void check_procedure_later(CheckerContext *c, ProcInfo *info) {
+gb_internal void check_procedure_later(Checker *c, ProcInfo *info) {
 	GB_ASSERT(info != nullptr);
 	GB_ASSERT(info != nullptr);
 	GB_ASSERT(info->decl != nullptr);
 	GB_ASSERT(info->decl != nullptr);
 
 
 	if (MULTITHREAD_CHECKER && global_procedure_body_in_worker_queue) {
 	if (MULTITHREAD_CHECKER && global_procedure_body_in_worker_queue) {
 		thread_pool_add_task(check_proc_info_worker_proc, info);
 		thread_pool_add_task(check_proc_info_worker_proc, info);
 	} else {
 	} else {
-		if (build_context.threaded_checker && global_procedure_body_in_worker_queue) {
-			GB_ASSERT(c->procs_to_check_queue != nullptr);
-		}
-
-		auto *queue = c->procs_to_check_queue ? c->procs_to_check_queue : &c->checker->procs_to_check_queue;
-		mpmc_enqueue(queue, info);
+		GB_ASSERT(global_procedure_body_in_worker_queue == false);
+		array_add(&c->procs_to_check, info);
 	}
 	}
 }
 }
 
 
-gb_internal void check_procedure_later(CheckerContext *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) {
+gb_internal void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) {
 	ProcInfo *info = gb_alloc_item(permanent_allocator(), ProcInfo);
 	ProcInfo *info = gb_alloc_item(permanent_allocator(), ProcInfo);
 	info->file  = file;
 	info->file  = file;
 	info->token = token;
 	info->token = token;
@@ -4677,11 +4671,7 @@ struct CollectEntityWorkerData {
 gb_global CollectEntityWorkerData *collect_entity_worker_data;
 gb_global CollectEntityWorkerData *collect_entity_worker_data;
 
 
 gb_internal WORKER_TASK_PROC(check_collect_entities_all_worker_proc) {
 gb_internal WORKER_TASK_PROC(check_collect_entities_all_worker_proc) {
-	isize thread_idx = 0;
-	if (current_thread) {
-		thread_idx = current_thread->idx;
-	}
-	CollectEntityWorkerData *wd = &collect_entity_worker_data[thread_idx];
+	CollectEntityWorkerData *wd = &collect_entity_worker_data[current_thread_index()];
 
 
 	Checker *c = wd->c;
 	Checker *c = wd->c;
 	CheckerContext *ctx = &wd->ctx;
 	CheckerContext *ctx = &wd->ctx;
@@ -4738,10 +4728,8 @@ gb_internal void check_export_entities_in_pkg(CheckerContext *ctx, AstPackage *p
 }
 }
 
 
 gb_internal WORKER_TASK_PROC(check_export_entities_worker_proc) {
 gb_internal WORKER_TASK_PROC(check_export_entities_worker_proc) {
-	isize thread_idx = current_thread ? current_thread->idx : 0;
-
 	AstPackage *pkg = (AstPackage *)data;
 	AstPackage *pkg = (AstPackage *)data;
-	auto *wd = &collect_entity_worker_data[thread_idx];
+	auto *wd = &collect_entity_worker_data[current_thread_index()];
 	check_export_entities_in_pkg(&wd->ctx, pkg, &wd->untyped);
 	check_export_entities_in_pkg(&wd->ctx, pkg, &wd->untyped);
 	return 0;
 	return 0;
 }
 }
@@ -5069,7 +5057,7 @@ gb_internal void calculate_global_init_order(Checker *c) {
 }
 }
 
 
 
 
-gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, ProcBodyQueue *procs_to_check_queue) {
+gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) {
 	if (pi == nullptr) {
 	if (pi == nullptr) {
 		return false;
 		return false;
 	}
 	}
@@ -5085,17 +5073,16 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u
 			}
 			}
 			return true;
 			return true;
 		}
 		}
+		if (e != nullptr && (e->flags & EntityFlag_ProcBodyChecked) != 0) {
+			GB_ASSERT(pi->decl->proc_checked);
+			return true;
+		}
+		pi->decl->proc_checked = true;
+		if (e != nullptr) {
+			e->flags |= EntityFlag_ProcBodyChecked;
+		}
 	}
 	}
 
 
-	CheckerContext ctx = make_checker_context(c);
-	defer (destroy_checker_context(&ctx));
-	reset_checker_context(&ctx, pi->file, untyped);
-	ctx.decl = pi->decl;
-
-	GB_ASSERT(procs_to_check_queue != nullptr || MULTITHREAD_CHECKER);
-
-	ctx.procs_to_check_queue = procs_to_check_queue;
-
 	GB_ASSERT(pi->type->kind == Type_Proc);
 	GB_ASSERT(pi->type->kind == Type_Proc);
 	TypeProc *pt = &pi->type->Proc;
 	TypeProc *pt = &pi->type->Proc;
 	String name = pi->token.string;
 	String name = pi->token.string;
@@ -5116,6 +5103,12 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u
 		}
 		}
 	}
 	}
 
 
+
+	CheckerContext ctx = make_checker_context(c);
+	defer (destroy_checker_context(&ctx));
+	reset_checker_context(&ctx, pi->file, untyped);
+	ctx.decl = pi->decl;
+
 	bool bounds_check    = (pi->tags & ProcTag_bounds_check)    != 0;
 	bool bounds_check    = (pi->tags & ProcTag_bounds_check)    != 0;
 	bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
 	bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
 
 
@@ -5138,24 +5131,14 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u
 		ctx.state_flags &= ~StateFlag_type_assert;
 		ctx.state_flags &= ~StateFlag_type_assert;
 	}
 	}
 
 
-	if (pi->body != nullptr && e != nullptr) {
-		GB_ASSERT((e->flags & EntityFlag_ProcBodyChecked) == 0);
-	}
-
 	check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body);
 	check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body);
-	MUTEX_GUARD_BLOCK(&pi->decl->proc_checked_mutex) {
-		if (e != nullptr) {
-			e->flags |= EntityFlag_ProcBodyChecked;
-		}
-		pi->decl->proc_checked = true;
-	}
 	add_untyped_expressions(&c->info, ctx.untyped);
 	add_untyped_expressions(&c->info, ctx.untyped);
 	return true;
 	return true;
 }
 }
 
 
 GB_STATIC_ASSERT(sizeof(isize) == sizeof(void *));
 GB_STATIC_ASSERT(sizeof(isize) == sizeof(void *));
 
 
-gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, ProcBodyQueue *q, UntypedExprInfoMap *untyped);
+gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped);
 
 
 gb_internal void check_unchecked_bodies(Checker *c) {
 gb_internal void check_unchecked_bodies(Checker *c) {
 	// NOTE(2021-02-26, bill): Sanity checker
 	// NOTE(2021-02-26, bill): Sanity checker
@@ -5193,15 +5176,13 @@ gb_internal void check_unchecked_bodies(Checker *c) {
 			}
 			}
 
 
 			debugf("unchecked: %.*s\n", LIT(e->token.string));
 			debugf("unchecked: %.*s\n", LIT(e->token.string));
-			mpmc_enqueue(&c->procs_to_check_queue, pi);
+			array_add(&c->procs_to_check, pi);
 		}
 		}
 	}
 	}
 
 
-	auto *q = &c->procs_to_check_queue;
-	ProcInfo *pi = nullptr;
-	while (mpmc_dequeue(q, &pi)) {
+	for (ProcInfo *pi : c->procs_to_check) {
 		Entity *e = pi->decl->entity;
 		Entity *e = pi->decl->entity;
-		if (consume_proc_info_queue(c, pi, q, &untyped)) {
+		if (consume_proc_info_queue(c, pi, &untyped)) {
 			add_dependency_to_set(c, e);
 			add_dependency_to_set(c, e);
 			GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked);
 			GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked);
 		}
 		}
@@ -5245,7 +5226,7 @@ gb_internal void check_test_procedures(Checker *c) {
 
 
 gb_global std::atomic<isize> total_bodies_checked;
 gb_global std::atomic<isize> total_bodies_checked;
 
 
-gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, ProcBodyQueue *q, UntypedExprInfoMap *untyped) {
+gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) {
 	GB_ASSERT(pi->decl != nullptr);
 	GB_ASSERT(pi->decl != nullptr);
 	if (pi->decl->parent && pi->decl->parent->entity) {
 	if (pi->decl->parent && pi->decl->parent->entity) {
 		Entity *parent = pi->decl->parent->entity;
 		Entity *parent = pi->decl->parent->entity;
@@ -5253,14 +5234,14 @@ gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, ProcBodyQueue
 		// This is prevent any possible race conditions in evaluation when multithreaded
 		// This is prevent any possible race conditions in evaluation when multithreaded
 		// NOTE(bill): In single threaded mode, this should never happen
 		// NOTE(bill): In single threaded mode, this should never happen
 		if (parent->kind == Entity_Procedure && (parent->flags & EntityFlag_ProcBodyChecked) == 0) {
 		if (parent->kind == Entity_Procedure && (parent->flags & EntityFlag_ProcBodyChecked) == 0) {
-			mpmc_enqueue(q, pi);
+			check_procedure_later(c, pi);
 			return false;
 			return false;
 		}
 		}
 	}
 	}
 	if (untyped) {
 	if (untyped) {
 		map_clear(untyped);
 		map_clear(untyped);
 	}
 	}
-	bool ok = check_proc_info(c, pi, untyped, q);
+	bool ok = check_proc_info(c, pi, untyped);
 	total_bodies_checked.fetch_add(1, std::memory_order_relaxed);
 	total_bodies_checked.fetch_add(1, std::memory_order_relaxed);
 	return ok;
 	return ok;
 }
 }
@@ -5273,12 +5254,9 @@ struct CheckProcedureBodyWorkerData {
 gb_global CheckProcedureBodyWorkerData *check_procedure_bodies_worker_data;
 gb_global CheckProcedureBodyWorkerData *check_procedure_bodies_worker_data;
 
 
 gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) {
 gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) {
-	isize thread_idx = 0;
-	if (current_thread) {
-		thread_idx = current_thread->idx;
-	}
-	UntypedExprInfoMap *untyped = &check_procedure_bodies_worker_data[thread_idx].untyped;
-	Checker *c = check_procedure_bodies_worker_data[thread_idx].c;
+	auto *wd = &check_procedure_bodies_worker_data[current_thread_index()];
+	UntypedExprInfoMap *untyped = &wd->untyped;
+	Checker *c = wd->c;
 
 
 	ProcInfo *pi = cast(ProcInfo *)data;
 	ProcInfo *pi = cast(ProcInfo *)data;
 
 
@@ -5294,7 +5272,7 @@ gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) {
 		}
 		}
 	}
 	}
 	map_clear(untyped);
 	map_clear(untyped);
-	bool ok = check_proc_info(c, pi, untyped, nullptr);
+	bool ok = check_proc_info(c, pi, untyped);
 	total_bodies_checked.fetch_add(1, std::memory_order_relaxed);
 	total_bodies_checked.fetch_add(1, std::memory_order_relaxed);
 	return !ok;
 	return !ok;
 }
 }
@@ -5321,13 +5299,11 @@ gb_internal void check_procedure_bodies(Checker *c) {
 	});
 	});
 
 
 	if (thread_count == 1) {
 	if (thread_count == 1) {
-		auto *this_queue = &c->procs_to_check_queue;
-
 		UntypedExprInfoMap *untyped = &check_procedure_bodies_worker_data[0].untyped;
 		UntypedExprInfoMap *untyped = &check_procedure_bodies_worker_data[0].untyped;
-
-		for (ProcInfo *pi = nullptr; mpmc_dequeue(this_queue, &pi); /**/) {
-			consume_proc_info_queue(c, pi, this_queue, untyped);
+		for_array(i, c->procs_to_check) {
+			consume_proc_info_queue(c, c->procs_to_check[i], untyped);
 		}
 		}
+		array_clear(&c->procs_to_check);
 
 
 		debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed));
 		debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed));
 		return;
 		return;
@@ -5335,12 +5311,12 @@ gb_internal void check_procedure_bodies(Checker *c) {
 
 
 	global_procedure_body_in_worker_queue = true;
 	global_procedure_body_in_worker_queue = true;
 
 
-	for (ProcInfo *pi = nullptr; mpmc_dequeue(&c->procs_to_check_queue, &pi); /**/) {
-		thread_pool_add_task(check_proc_info_worker_proc, pi);
+	isize prev_procs_to_check_count = c->procs_to_check.count;
+	for_array(i, c->procs_to_check) {
+		thread_pool_add_task(check_proc_info_worker_proc, c->procs_to_check[i]);
 	}
 	}
-
-	isize global_remaining = c->procs_to_check_queue.count.load(std::memory_order_relaxed);
-	GB_ASSERT(global_remaining == 0);
+	GB_ASSERT(prev_procs_to_check_count == c->procs_to_check.count);
+	array_clear(&c->procs_to_check);
 
 
 	thread_pool_wait();
 	thread_pool_wait();
 
 

+ 1 - 5
src/checker.hpp

@@ -418,8 +418,6 @@ struct CheckerContext {
 	Scope *    polymorphic_scope;
 	Scope *    polymorphic_scope;
 
 
 	Ast *assignment_lhs_hint;
 	Ast *assignment_lhs_hint;
-
-	ProcBodyQueue *procs_to_check_queue;
 };
 };
 
 
 
 
@@ -430,9 +428,7 @@ struct Checker {
 	CheckerContext builtin_ctx;
 	CheckerContext builtin_ctx;
 
 
 	MPMCQueue<Entity *> procs_with_deferred_to_check;
 	MPMCQueue<Entity *> procs_with_deferred_to_check;
-
-	ProcBodyQueue procs_to_check_queue;
-	Semaphore procs_to_check_semaphore;
+	Array<ProcInfo *> procs_to_check;
 
 
 	// TODO(bill): Technically MPSC queue
 	// TODO(bill): Technically MPSC queue
 	MPMCQueue<UntypedExprInfo> global_untyped_queue;
 	MPMCQueue<UntypedExprInfo> global_untyped_queue;

+ 4 - 0
src/thread_pool.cpp

@@ -21,6 +21,10 @@ struct ThreadPool {
 	Futex tasks_left;
 	Futex tasks_left;
 };
 };
 
 
+gb_internal isize current_thread_index(void) {
+	return current_thread ? current_thread->idx : 0;
+}
+
 gb_internal void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count, char const *worker_name) {
 gb_internal void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count, char const *worker_name) {
 	pool->allocator = a;
 	pool->allocator = a;
 	slice_init(&pool->threads, a, thread_count + 1);
 	slice_init(&pool->threads, a, thread_count + 1);