]> Nishi Git Mirror - gwion.git/commitdiff
:art: Split Call and unwind
authorfennecdjay <astor.jeremie@wanadoo.fr>
Sun, 10 Mar 2019 14:02:52 +0000 (15:02 +0100)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Sun, 10 Mar 2019 14:02:52 +0000 (15:02 +0100)
examples/complex/event.gw
examples/shreduler_coverage.gw
include/import.h
include/memoize.h
include/opcode.h
include/plug.h
opcode.txt
src/emit/emit.c
src/emit/memoize.c
src/vm/shreduler.c
src/vm/vm.c

index ab60daea8cb859ab69b142115605b863a75e4962..829410753d19391be054d3a8ece4867ad1d2e3c8 100644 (file)
@@ -1,5 +1,6 @@
 Event e;
 spork {second => now; e.broadcast(); };
+spork \{second => now; e.broadcast(); }();
 //2::second => now;
 .2::second => now;
 e => now;
index a06ba55c8c6af94382a31ac8aba8192978b1d3f4..944408ef070013b7946a59d92568cb75a8237adf 100644 (file)
@@ -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;
index a32d4591edab727f4c383df68460f11588900448..51cfa3418f1b506f94c81c8ae95cbec2108f1c7f 100644 (file)
@@ -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)))
index ab52d618e918c22d6706d364bcc5a4afa8e60126..683d342b549389da011fdc17e0ce7817eab3e824 100644 (file)
@@ -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
index 1e2579c3a846f3a88cae26d82dbe6b4b68bafff2..256d2108e993556ca8a8e87b5df9e7fcff76b02c 100644 (file)
@@ -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
index 96653fd523dfcd2a704c6b0a08cddb163b3b9f9e..ec96647856aa095c614c91538d05da0b515dbf7d 100644 (file)
@@ -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)
 
index 1764f4046cbe7d5d821af0fe8b5f799af5aee371..d31f84bedd5fbd9cecb2d750453ebc1a85fdd971 100644 (file)
@@ -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
index 56fe9dfeab61d6c3a54ad7c3837f43b8fa579b13..fe808ee08113a9b55402523d0fc52a9922d8c269 100644 (file)
@@ -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,
index 08db52c03b3330a5e345d3480abb56c027450df0..f6d0f407cccf079f422cf21fe17a8e2b467ed2bb 100644 (file)
@@ -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) {
index ea3ecde1ced0f8918e227c44ee1401004985f8e8..cc0df7380b4e0479e2d69529f76ad6c3b438938b 100644 (file)
@@ -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);
   }
 }
index 6c4928feda6d3a12d2311e2f2cc64b1356717c2b..f019466693e9ee43d7f355936cd8551f6293a603 100644 (file)
@@ -230,7 +230,7 @@ ANN void vm_run(const VM* vm) { /* lgtm [cpp/use-of-goto] */
     &&baseint, &&basefloat, &&baseother, &&baseaddr,
     &&regdup, &&regdup2,
     &&memsetimm,
-    &&regpop, &&regpushme, &&regpushmaybe,
+    &&regpushme, &&regpushmaybe,
     &&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, &&regpop, &&regtomem, &&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()