Event e;
spork {second => now; e.broadcast(); };
+spork \{second => now; e.broadcast(); }();
//2::second => now;
.2::second => now;
e => now;
+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;
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)))
#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;
#define MEMOIZE_CALL
#define MEMOIZE_STORE
#define MEMOIZE_INI
+#define MEMOIZE_SET(a)
#endif
#endif
RegDup,
RegDup2,
MemSetImm,
- RegPop,
RegPushMe,
RegPushMaybe,
FuncReturn,
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,
#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
#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
#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)
RegDup
RegDup2
MemSetImm
-RegPop
RegPushMe
RegPushMaybe
FuncReturn
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
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
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;
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
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,
}
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) {
INSTR(MemoizeCall) {
if(memoize_get(shred))
- ++shred->pc;
+ shred->pc += instr->m_val;
}
INSTR(MemoizeStore) {
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);
}
}
&&baseint, &&basefloat, &&baseother, &&baseaddr,
&®dup, &®dup2,
&&memsetimm,
- &®pop, &®pushme, &®pushmaybe,
+ &®pushme, &®pushmaybe,
&&funcreturn,
&&_goto,
&&allocint, &&allocfloat, &&allocother, &&allocaddr,
&&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,
};
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;
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;
intrassign:
reg -= SZ_INT;
-/*assert(*(m_int**)reg);*/
**(m_int**)reg = *(m_int*)(reg-SZ_INT);
DISPATCH()
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()
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)
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;
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;
DISPATCH();
gcend:
while((a.obj = (M_Object)vector_pop(&shred->gc))) {
- assert(a.obj);
_release(a.obj, shred);
}
DISPATCH()