From: fennecdjay Date: Sun, 10 Mar 2019 14:02:52 +0000 (+0100) Subject: :art: Split Call and unwind X-Git-Tag: nightly~2753^2~12 X-Git-Url: http://10.11.0.4:5575/?a=commitdiff_plain;h=f21549f9dd19ebc526cb8a0eb286bd81b2c69447;p=gwion.git :art: Split Call and unwind --- diff --git a/examples/complex/event.gw b/examples/complex/event.gw index ab60daea..82941075 100644 --- a/examples/complex/event.gw +++ b/examples/complex/event.gw @@ -1,5 +1,6 @@ Event e; spork {second => now; e.broadcast(); }; +spork \{second => now; e.broadcast(); }(); //2::second => now; .2::second => now; e => now; diff --git a/examples/shreduler_coverage.gw b/examples/shreduler_coverage.gw index a06ba55c..944408ef 100644 --- a/examples/shreduler_coverage.gw +++ b/examples/shreduler_coverage.gw @@ -1,3 +1,6 @@ +fun void t() { 2::second => now; <<<"child ", me.id()>>>; }; +spork t(); +spork \{ 2::second => now; <<<"child ", me.id()>>>; }(); spork { 2::second => now; <<<"child ", me.id()>>>; }; <<<"start">>>; second => now; diff --git a/include/import.h b/include/import.h index a32d4591..51cfa341 100644 --- a/include/import.h +++ b/include/import.h @@ -5,13 +5,13 @@ typedef void (*f_xtor)(const M_Object o, const m_bit*, const VM_Shred); //typedef void (*f_xtor)(const M_Object o, const VM_Shred); typedef void (*f_mfun)(const M_Object o, const m_bit* RETURN, const VM_Shred sh); -typedef void (*f_sfun)(const m_bit* RETURN, const VM_Shred sh); -//typedef void (*f_sfun)(const m_bit*, const m_bit* RETURN, const VM_Shred sh); +//typedef void (*f_sfun)(const m_bit* RETURN, const VM_Shred sh); +typedef void (*f_sfun)(const m_bit*, const m_bit* RETURN, const VM_Shred sh); typedef void (*f_xfun)(); typedef struct Gwi_* Gwi; #define MFUN(a) ANN void a(const M_Object o __attribute__((unused)), const m_bit* RETURN __attribute__((unused)), const VM_Shred shred __attribute__((unused))) -#define SFUN(a) ANN void a(const m_bit* RETURN __attribute__((unused)), const VM_Shred shred __attribute__((unused))) +#define SFUN(a) ANN void a(const M_Object o __attribute__((unused)), const m_bit* RETURN __attribute__((unused)), const VM_Shred shred __attribute__((unused))) //#define SFUN(a) ANN void a(const m_bit* mem __attribute__((unused)), const m_bit* RETURN //__attribute__((unused)), const VM_Shred shred __attribute__((unused))) #define CTOR(a) ANN void a(const M_Object o, const m_bit* _ __attribute__((unused)), const VM_Shred shred __attribute__((unused))) diff --git a/include/memoize.h b/include/memoize.h index ab52d618..683d342b 100644 --- a/include/memoize.h +++ b/include/memoize.h @@ -2,7 +2,8 @@ #define __MEMOIZE #ifndef NOMEMOIZE -#define MEMOIZE_CALL if(GET_FLAG(f, pure)) emit_add_instr(emit, MemoizeCall); +#define MEMOIZE_CALL const Instr memoize = !GET_FLAG(f, pure) ? NULL : emit_add_instr(emit, MemoizeCall); +#define MEMOIZE_SET(a) if(memoize)memoize->m_val = a + 2; #define MEMOIZE_STORE if(GET_FLAG(emit->env->func, pure)) emit_add_instr(emit, MemoizeStore); #define MEMOIZE_INI if(GET_FLAG(func, pure)) func->code->memoize = memoize_ini(func, kindof(func->def->ret_type->size, !func->def->ret_type->size)); typedef struct Memoize_ * Memoize; @@ -14,5 +15,6 @@ INSTR(MemoizeStore); #define MEMOIZE_CALL #define MEMOIZE_STORE #define MEMOIZE_INI +#define MEMOIZE_SET(a) #endif #endif diff --git a/include/opcode.h b/include/opcode.h index 1e2579c3..256d2108 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -18,7 +18,6 @@ enum { RegDup, RegDup2, MemSetImm, - RegPop, RegPushMe, RegPushMaybe, FuncReturn, @@ -119,15 +118,21 @@ enum { CastI2F, CastF2I, Time_Advance, - FuncUsr, + SetCode, + FuncPtr, FuncMember, - FuncStatic, + FuncUsr, + RegPop, + Reg2Mem, + Overflow, + Next, + FuncUsrEnd, + FuncMemberEnd, SporkIni, SporkFunc, SporkThis, SporkExp, SporkEnd, - FuncPtr, BranchEqInt, BranchNeqInt, BranchEqFloat, @@ -175,7 +180,6 @@ enum { #define RegDup (f_instr)RegDup #define RegDup2 (f_instr)RegDup2 #define MemSetImm (f_instr)MemSetImm -#define RegPop (f_instr)RegPop #define RegPushMe (f_instr)RegPushMe #define RegPushMaybe (f_instr)RegPushMaybe #define FuncReturn (f_instr)FuncReturn @@ -276,15 +280,21 @@ enum { #define CastI2F (f_instr)CastI2F #define CastF2I (f_instr)CastF2I #define Time_Advance (f_instr)Time_Advance -#define FuncUsr (f_instr)FuncUsr +#define SetCode (f_instr)SetCode +#define FuncPtr (f_instr)FuncPtr #define FuncMember (f_instr)FuncMember -#define FuncStatic (f_instr)FuncStatic +#define FuncUsr (f_instr)FuncUsr +#define RegPop (f_instr)RegPop +#define Reg2Mem (f_instr)Reg2Mem +#define Overflow (f_instr)Overflow +#define Next (f_instr)Next +#define FuncUsrEnd (f_instr)FuncUsrEnd +#define FuncMemberEnd (f_instr)FuncMemberEnd #define SporkIni (f_instr)SporkIni #define SporkFunc (f_instr)SporkFunc #define SporkThis (f_instr)SporkThis #define SporkExp (f_instr)SporkExp #define SporkEnd (f_instr)SporkEnd -#define FuncPtr (f_instr)FuncPtr #define BranchEqInt (f_instr)BranchEqInt #define BranchNeqInt (f_instr)BranchNeqInt #define BranchEqFloat (f_instr)BranchEqFloat diff --git a/include/plug.h b/include/plug.h index 96653fd5..ec966478 100644 --- a/include/plug.h +++ b/include/plug.h @@ -21,7 +21,7 @@ void plug_end(const Gwion gwion); #define GWMODEND_NAME gwmodend #define GWDRIVER_NAME gwmodend #define GWMODSTR(a) m_str GWMODSTR_NAME() { return #a; } -#define GWMODINI(a) ANN void* GWMODINI_NAME(const Gwion gwion, const Vector args) +#define GWMODINI(a) ANN2(1) void* GWMODINI_NAME(const Gwion gwion, const Vector args) #define GWMODEND(a) ANN void GWMODEND_NAME(const Gwion gwion, void* self) #define GWDRIVER(a) ANN void GWDRIVER_NAME(Driver* d) diff --git a/opcode.txt b/opcode.txt index 1764f404..d31f84be 100644 --- a/opcode.txt +++ b/opcode.txt @@ -15,7 +15,6 @@ RegPushBase4 RegDup RegDup2 MemSetImm -RegPop RegPushMe RegPushMaybe FuncReturn @@ -116,15 +115,21 @@ float_int_r_div CastI2F CastF2I Time_Advance -FuncUsr +SetCode +FuncPtr FuncMember -FuncStatic +FuncUsr +RegPop +Reg2Mem +Overflow +Next +FuncUsrEnd +FuncMemberEnd SporkIni SporkFunc SporkThis SporkExp SporkEnd -FuncPtr BranchEqInt BranchNeqInt BranchEqFloat diff --git a/src/emit/emit.c b/src/emit/emit.c index 56fe9dfe..fe808ee0 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -190,7 +190,12 @@ ANN void emit_ext_ctor(const Emitter emit, const VM_Code code) { GWDEBUG_EXE push_f->m_val = (m_uint)code; const Instr offset = emit_add_instr(emit, RegSetImm); offset->m_val = emit_code_offset(emit); - emit_add_instr(emit, !GET_FLAG(code, builtin) ? FuncUsr : FuncMember); + const Instr prelude = emit_add_instr(emit, !GET_FLAG(code, builtin) ? FuncUsr : FuncMember); + prelude->m_val2 = 2; + prelude->m_val = SZ_INT; + emit_add_instr(emit, Reg2Mem); + const Instr next = emit_add_instr(emit, Overflow); + next->m_val2 = offset->m_val; } ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) { GWDEBUG_EXE @@ -732,7 +737,7 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) { return GW_OK; } -static m_bool emit_template_code(const Emitter emit, const Func f) { +ANN static m_bool emit_template_code(const Emitter emit, const Func f) { if(GET_FLAG(f, ref)) CHECK_BB(traverse_template(emit->env, f->value_ref->owner_class->def)) const Value v = f->value_ref; @@ -742,16 +747,41 @@ static m_bool emit_template_code(const Emitter emit, const Func f) { return push_func_code(emit, f); } -ANN static Instr emit_call(const Emitter emit, const Func f) { - MEMOIZE_CALL +ANN static Instr get_prelude(const Emitter emit, const Func f) { + Instr instr; const Type t = actual_type(f->value_ref->type); - if(isa(t, t_fptr) < 0) { - const f_instr exec = GET_FLAG(f->def, builtin) ? GET_FLAG(f, member) ? - FuncMember : FuncStatic : FuncUsr; - return emit_add_instr(emit, exec); + if(isa(t, t_fptr) < 0) + instr = emit_add_instr(emit, !GET_FLAG(f, builtin) ? FuncUsr : SetCode); + else { + emit_add_instr(emit, GWOP_EXCEPT); + instr = emit_add_instr(emit, FuncPtr); } - emit_add_instr(emit, GWOP_EXCEPT); - return emit_add_instr(emit, FuncPtr); + instr->m_val2 = 1; + return instr; +} + +ANN static Instr emit_call(const Emitter emit, const Func f) { + MEMOIZE_CALL + f_instr exec; + const Instr prelude = get_prelude(emit, f); + if(f->def->stack_depth) { + const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0; + prelude->m_val = f->def->stack_depth; + if(member) { + const Instr instr = emit_add_instr(emit, Reg2Mem); + instr->m_val2 = f->def->stack_depth - SZ_INT; + ++prelude->m_val2; + } + for(m_uint i = 0; i < f->def->stack_depth - member; i += SZ_INT) { + const Instr instr = emit_add_instr(emit, Reg2Mem); + instr->m_val = (instr->m_val2 = i) + member; + ++prelude->m_val2; + } + exec = Overflow; + } else + exec = Next; + MEMOIZE_SET(prelude->m_val2); + return emit_add_instr(emit, exec); } ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { GWDEBUG_EXE @@ -780,8 +810,9 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { GWDEBUG_EXE const Instr offset = emit_add_instr(emit, RegSetImm); offset->m_val = emit_code_offset(emit); const Instr instr = emit_call(emit, f); - const m_uint size = instr->m_val = f->def->ret_type->size; - return (m_bool)(instr->m_val2 = kindof(size, !size)); + instr->m_val = f->def->ret_type->size; + instr->m_val2 = offset->m_val; + return GW_OK; } ANN2(1,2) static m_bool emit_exp_spork_finish(const Emitter emit, const VM_Code code, diff --git a/src/emit/memoize.c b/src/emit/memoize.c index 08db52c0..f6d0f407 100644 --- a/src/emit/memoize.c +++ b/src/emit/memoize.c @@ -70,9 +70,10 @@ static inline void memoize_set(Memoize m, const m_bit* arg) { } m_bool memoize_get(VM_Shred shred) { -// const VM_Code code = *(VM_Code*)REG(-SZ_INT * 2); const VM_Code code = *(VM_Code*)REG(-SZ_INT); const Memoize m = code->memoize; + if(!m) + return GW_OK; const m_bit* arg = REG(-(SZ_INT + m->arg_sz + (m_uint)m->member)); const m_uint size = vector_size(&m->v); for(m_uint i = 0; i < size; ++i) { @@ -89,7 +90,7 @@ m_bool memoize_get(VM_Shred shred) { INSTR(MemoizeCall) { if(memoize_get(shred)) - ++shred->pc; + shred->pc += instr->m_val; } INSTR(MemoizeStore) { diff --git a/src/vm/shreduler.c b/src/vm/shreduler.c index ea3ecde1..cc0df738 100644 --- a/src/vm/shreduler.c +++ b/src/vm/shreduler.c @@ -36,10 +36,24 @@ ANN static void shreduler_parent(const VM_Shred out, const Vector v) { out->tick->parent->child.ptr = NULL; } } +#include "instr.h" +ANN static void unwind(const VM_Shred shred) { + VM_Code code = shred->code; + while(1) { + const f_instr exec = + (f_instr)(m_uint)((Instr)vector_back(code->instr))->opcode; + if(exec == FuncReturn) { + code = *(VM_Code*)(shred->mem - SZ_INT*3); + REM_REF(code); + shred->mem -= *(m_uint*)(shred->mem - SZ_INT); + } else break; + } +} ANN static void shreduler_child(const Shreduler s, const Vector v) { for(m_uint i = vector_size(v) + 1; --i;) { const VM_Shred child = (VM_Shred)vector_at(v, i - 1); + unwind(child); shreduler_remove(s, child, 1); } } diff --git a/src/vm/vm.c b/src/vm/vm.c index 6c4928fe..f0194666 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -230,7 +230,7 @@ ANN void vm_run(const VM* vm) { /* lgtm [cpp/use-of-goto] */ &&baseint, &&basefloat, &&baseother, &&baseaddr, &®dup, &®dup2, &&memsetimm, - &®pop, &®pushme, &®pushmaybe, + &®pushme, &®pushmaybe, &&funcreturn, &&_goto, &&allocint, &&allocfloat, &&allocother, &&allocaddr, @@ -259,9 +259,9 @@ ANN void vm_run(const VM* vm) { /* lgtm [cpp/use-of-goto] */ &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv, &&itof, &&ftoi, &&timeadv, - &&funcusr, &&funcmember, &&funcstatic, + &&setcode, &&funcptr, &&funcmember, + &&funcusr, &®pop, &®tomem, &&overflow, &&next, &&funcusrend, &&funcmemberend, &&sporkini, &&sporkfunc, &&sporkthis, &&sporkexp, &&sporkend, - &&funcptr, &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&decintaddr, &&initloop, &&newobj, @@ -274,18 +274,16 @@ ANN void vm_run(const VM* vm) { /* lgtm [cpp/use-of-goto] */ }; const Shreduler s = vm->shreduler; register VM_Shred shred; - +register m_bit next; while((shred = shreduler_get(s))) { register VM_Code code = shred->code; -register -m_uint* ip = code->instr->ptr + OFFSET; +register m_uint* ip = code->instr->ptr + OFFSET; register size_t pc = shred->pc; register m_bit* reg = shred->reg; register m_bit* mem = shred->mem; - register union { M_Object obj; VM_Code code; @@ -370,9 +368,6 @@ regdup2: memsetimm: *(m_uint*)(mem+instr->m_val) = instr->m_val2; DISPATCH(); -regpop: - reg -= instr->m_val; - DISPATCH(); regpushme: *(M_Object*)reg = shred->info->me; reg += SZ_INT; @@ -437,7 +432,6 @@ intcmp: SELF(m_int, SZ_INT, ~) intrassign: reg -= SZ_INT; -/*assert(*(m_int**)reg);*/ **(m_int**)reg = *(m_int*)(reg-SZ_INT); DISPATCH() @@ -555,92 +549,56 @@ shred->reg = reg; shred->mem = mem; shred->pc = pc; break; - +setcode: + a.code = *(VM_Code*)(reg-SZ_INT); +funcptr: + if(!GET_FLAG((VM_Code)a.code, builtin)) + goto funcusr; +funcmember: + reg -= SZ_INT; + a.code = *(VM_Code*)reg; + mem += *(m_uint*)(reg + SZ_INT); + next = FuncMemberEnd; + goto *dispatch[(m_uint)RegPop]; funcusr: { reg -= SZ_INT; + a.code = *(VM_Code*)reg; register const m_uint push = *(m_uint*)(reg + SZ_INT) + *(m_uint*)(mem-SZ_INT); mem += push; *(m_uint*) mem = push;mem += SZ_INT; *(VM_Code*) mem = code; mem += SZ_INT; - *(m_uint*) mem = pc; mem += SZ_INT; - pc = 0; - code = *(VM_Code*)reg; - ip = code->instr->ptr + OFFSET; - m_uint stack_depth = code->stack_depth; - *(m_uint*) mem = stack_depth; mem += SZ_INT; - if(stack_depth) { - register const m_uint f = GET_FLAG(code, member) ? SZ_INT : 0; - if(f) { - *(m_uint*)mem = *(m_uint*)(reg - SZ_INT); - stack_depth -= SZ_INT; - } - reg-=code->stack_depth; -// LOOP_OPTIM - for(m_uint i = 0; i < stack_depth; i+= SZ_INT) - *(m_uint*)(mem+i+f) = *(m_uint*)(reg+i); - } - if(overflow_(mem, shred)) - Except(shred, "StackOverflow"); + *(m_uint*) mem = pc + instr->m_val2; mem += SZ_INT; + *(m_uint*) mem = a.code->stack_depth; mem += SZ_INT; + next = FuncUsrEnd; +// goto *dispatch[(m_uint)RegPop]; } -DISPATCH(); -funcmember: -{ - reg -= SZ_INT; - a.code = *(VM_Code*)reg; - register const m_uint local_depth = *(m_uint*)(reg + SZ_INT); - register m_bit* m = mem + local_depth; -// assert(a.code); - register const m_uint stack_depth = a.code->stack_depth; - register const m_uint depth = stack_depth -SZ_INT; - reg -= stack_depth; - *(m_uint*)m = *(m_uint*)(reg + depth); -// LOOP_OPTIM - for(m_uint i = 0; i < depth; i+= SZ_INT) - *(m_uint*)(m+i+SZ_INT) = *(m_uint*)(reg+i); - if(overflow_(m, shred)) +regpop: + reg -= instr->m_val; + DISPATCH(); +regtomem: + *(m_uint*)(mem+instr->m_val) = *(m_uint*)(reg+instr->m_val2); + DISPATCH() +overflow: + if(overflow_(mem, shred)) Except(shred, "StackOverflow"); - shred->mem = m; +next: + goto *dispatch[next]; +funcusrend: + ip = (code = a.code)->instr->ptr + OFFSET; + pc = 0; + DISPATCH(); +funcmemberend: + shred->mem = mem; + shred->reg = reg; shred->pc = pc; shred->code = code; - if(GET_FLAG(a.code, ctor)) { - register const f_xtor f = (f_xtor)a.code->native_func; - f(*(M_Object*)m, NULL, shred);// callnat - goto funcend2;//2 - } - register const f_mfun f = (f_mfun)a.code->native_func; - f((*(M_Object*)m), reg, shred);//call native - goto funcend; -} -funcstatic: -{ - reg -= SZ_INT; - a.code = *(VM_Code*)reg; - register const m_uint local_depth = *(m_uint*)(reg + SZ_INT); - register m_bit* m = mem + local_depth; - //assert(a.code); - register const m_uint stack_depth = a.code->stack_depth; - if(stack_depth) { - reg -= stack_depth; -// LOOP_OPTIM - for(m_uint i = 0; i < stack_depth; i+= SZ_INT) - *(m_uint*)(m+i) = *(m_uint*)(reg+i); - } - if(overflow_(m, shred)) - Except(shred, "StackOverflow"); -// shred->reg = reg; - shred->mem = m; - shred->pc = pc; - register const f_sfun f = (f_sfun)a.code->native_func; - f(reg, shred); -funcend: - shred->reg = reg += instr->m_val; -funcend2: - shred->mem = mem; + ((f_mfun)a.code->native_func)((*(M_Object*)mem), reg, shred); + reg += instr->m_val; + shred->mem = (mem -= instr->m_val2); if(!s->curr)break; pc = shred->pc; DISPATCH() -} sporkini: a.child = init_spork_shred(shred, (VM_Code)instr->m_val); DISPATCH() @@ -662,13 +620,6 @@ sporkexp: sporkend: *(M_Object*)(reg-SZ_INT) = a.child->info->me; DISPATCH() -funcptr: - if(!GET_FLAG((VM_Code)a.code, builtin)) - goto funcusr; - else if(GET_FLAG((VM_Code)a.code, member)) - goto funcmember; - else - goto funcstatic; brancheqint: reg -= SZ_INT; if(!*(m_uint*)reg) @@ -701,7 +652,6 @@ newobj: reg += SZ_INT; DISPATCH() addref: -// assert(instr->m_val ? *(m_bit**)(reg-SZ_INT) : reg); // scan-build if((a.obj = instr->m_val ? **(M_Object**)(reg-SZ_INT) : *(M_Object*)(reg-SZ_INT))) ++a.obj->ref; @@ -709,7 +659,6 @@ addref: assign: reg -= SZ_INT; a.obj = *(M_Object*)(reg-SZ_INT); -// assert(*(M_Object**)reg); // scan-build const M_Object tgt = **(M_Object**)reg; if(tgt) { --tgt->ref; @@ -782,7 +731,6 @@ gcadd: DISPATCH(); gcend: while((a.obj = (M_Object)vector_pop(&shred->gc))) { - assert(a.obj); _release(a.obj, shred); } DISPATCH()