From d2b66f394c28480d1f429c3d4fe1548a8c995f73 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 10 Sep 2020 21:12:49 +0200 Subject: [PATCH] :art: Introduce TypedSpork --- src/emit/emit.c | 2 +- src/lib/func.c | 28 ++++++++++++++++++++-------- src/lib/shred.c | 16 +++++++++------- tests/fork/fork_call.gw | 9 +++++++++ 4 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 tests/fork/fork_call.gw diff --git a/src/emit/emit.c b/src/emit/emit.c index dcb4b580..0329cd1d 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1245,7 +1245,7 @@ ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) { const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL; const Instr instr = emit_add_instr(emit, ForkIni); instr->m_val = (m_uint)sp->vm_code; - instr->m_val2 = f ? f->def->base->ret_type->size : 0; + instr->m_val2 = f ? sp->type->size : 0; return instr; } diff --git a/src/lib/func.c b/src/lib/func.c index e1f3479b..da0f8586 100644 --- a/src/lib/func.c +++ b/src/lib/func.c @@ -288,18 +288,30 @@ static OP_EMIT(opem_fptr_impl) { ANN Type check_exp_unary_spork(const Env env, const Stmt code); +ANN static void fork_exp(const Env env, const Exp_Unary* unary) { + const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, unary->exp); + const Stmt_List list = new_stmt_list(env->gwion->mp, stmt, NULL); + const Stmt code = new_stmt_code(env->gwion->mp, list); + ((Exp_Unary*)unary)->exp = NULL; + ((Exp_Unary*)unary)->code = code; +} + +ANN static Type fork_type(const Env env, const Exp_Unary* unary) { + const Type t = unary->exp->info->type; + fork_exp(env, unary); + if(t == env->gwion->type[et_void]) + return env->gwion->type[et_fork]; + Type_Decl td0 = { .xid=insert_symbol(t->name), .pos=exp_self(unary)->pos }; + struct Type_List_ tl = { .td=&td0 }; + Type_Decl td = { .xid=insert_symbol("TypedFork"), .types=&tl, .pos=exp_self(unary)->pos }; + return known_type(env, &td); +} + static OP_CHECK(opck_spork) { const Exp_Unary* unary = (Exp_Unary*)data; if(unary->exp && unary->exp->exp_type == ae_exp_call) { const m_bool is_spork = unary->op == insert_symbol("spork"); - if(!is_spork) { - const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, unary->exp); - const Stmt_List list = new_stmt_list(env->gwion->mp, stmt, NULL); - const Stmt code = new_stmt_code(env->gwion->mp, list); - ((Exp_Unary*)unary)->exp = NULL; - ((Exp_Unary*)unary)->code = code; - } - return env->gwion->type[is_spork ? et_shred : et_fork]; + return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary); } if(unary->code) { ++env->scope->depth; diff --git a/src/lib/shred.c b/src/lib/shred.c index 1c067f23..33dadda8 100644 --- a/src/lib/shred.c +++ b/src/lib/shred.c @@ -13,13 +13,12 @@ #include "specialid.h" #include "gwi.h" -static m_int o_fork_thread, o_fork_cond, o_fork_mutex, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize, o_fork_ptr; +static m_int o_fork_thread, o_fork_cond, o_fork_mutex, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize; #define FORK_THREAD(o) *(THREAD_TYPE*)(o->data + o_fork_thread) #define FORK_COND(o) *(THREAD_COND_TYPE*)(o->data + o_fork_cond) #define FORK_MUTEX(o) *(MUTEX_TYPE*)(o->data + o_fork_mutex) #define FORK_RETSIZE(o) *(m_int*)(o->data + o_fork_retsize) -#define FORK_PTR(o) *(m_uint**)(o->data + o_fork_ptr) VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) { const VM_Shred sh = new_vm_shred(shred->info->mp, code); @@ -199,7 +198,6 @@ static DTOR(fork_dtor) { vector_init(&parent->gwion->data->child2); vector_add(&parent->gwion->data->child2, (vtype)ME(o)->info->vm->gwion); REM_REF(ME(o)->code, ME(o)->info->vm->gwion); - mp_free2(shred->info->vm->gwion->mp, FORK_RETSIZE(o), FORK_PTR(o)); MUTEX_UNLOCK(parent->shreduler->mutex); } @@ -263,7 +261,7 @@ struct ThreadLauncher *tl = data; vm_run(vm); ++vm->bbq->pos; } - memcpy(FORK_PTR(me), ME(me)->reg, FORK_RETSIZE(me)); + memcpy(me->data + vm->gwion->type[et_fork]->nspc->info->offset, *(m_bit**)ME(me)->reg, FORK_RETSIZE(me)); gwion_end_child(ME(me), vm->gwion); MUTEX_LOCK(vm->parent->shreduler->mutex); *(m_int*)(me->data + o_fork_done) = 1; @@ -275,7 +273,6 @@ struct ThreadLauncher *tl = data; ANN void fork_launch(const M_Object o, const m_uint sz) { FORK_RETSIZE(o) = sz; - FORK_PTR(o) = mp_calloc2(ME(o)->info->vm->gwion->mp, sz); MUTEX_SETUP(FORK_MUTEX(o)); THREAD_COND_SETUP(FORK_COND(o)); struct ThreadLauncher tl = { .mutex=FORK_MUTEX(o), .cond=FORK_COND(o), .vm=ME(o)->info->vm }; @@ -399,13 +396,18 @@ GWION_IMPORT(shred) { GWI_BB((o_fork_ev = gwi_item_end(gwi, ae_flag_const, NULL))) gwi_item_ini(gwi, "int", "retsize"); GWI_BB((o_fork_retsize = gwi_item_end(gwi, ae_flag_const, NULL))) - gwi_item_ini(gwi, "@internal", "@ptr"); - GWI_BB((o_fork_ptr = gwi_item_end(gwi, ae_flag_const, NULL))) gwi_func_ini(gwi, "void", "join"); GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none)) gwi_func_ini(gwi, "void", "test_cancel"); GWI_BB(gwi_func_end(gwi, fork_test_cancel, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) SET_FLAG((t_fork), abstract); + + const Type t_typed = gwi_class_ini(gwi, "<~A~>TypedFork", "Fork"); + gwi_item_ini(gwi, "A", "retval"); + GWI_BB((gwi_item_end(gwi, ae_flag_const, NULL))) + GWI_BB(gwi_class_end(gwi)) + SET_FLAG((t_typed), abstract); + return GW_OK; } diff --git a/tests/fork/fork_call.gw b/tests/fork/fork_call.gw new file mode 100644 index 00000000..9f01711f --- /dev/null +++ b/tests/fork/fork_call.gw @@ -0,0 +1,9 @@ +#! fork me.id() @=> auto ref sh; +fun int test() { + return 12; +} + +fork test() @=> <~int~>TypedFork ref sh; +<<< typeof(sh) >>>; +sh.ev => now; +<<< sh.retval >>>; -- 2.43.0