]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve unwind
authorJérémie Astor <fennecdjay@gmail.com>
Thu, 12 Aug 2021 20:57:54 +0000 (22:57 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Thu, 12 Aug 2021 20:57:54 +0000 (22:57 +0200)
include/shreduler_private.h
plug
src/gwion.c
src/lib/shred.c
src/vm/shreduler.c
src/vm/vm.c

index 9689934881d78c10389c28c5c2823475d57118af..65185eef0506285c53539df2efb01c3927f1389c 100644 (file)
@@ -4,9 +4,13 @@ struct Shreduler_ {
   struct BBQ_ *      bbq;
   struct ShredTick_ *list;
   struct ShredTick_ *curr;
-  struct Vector_     shreds;
+  struct Vector_     active_shreds;
   MUTEX_TYPE         mutex;
   size_t             shred_ids;
+  struct Vector_     killed_shreds;
   bool               loop;
 };
+
+ANN Shreduler new_shreduler(const MemPool mp);
+ANN void free_shreduler(const MemPool mp, const Shreduler s);
 #endif
diff --git a/plug b/plug
index a4a346eb4a993b208af212b3cb5873e74f4bddd2..de59c0509836ecb3eb7f5fbe2c621db137aa66ab 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit a4a346eb4a993b208af212b3cb5873e74f4bddd2
+Subproject commit de59c0509836ecb3eb7f5fbe2c621db137aa66ab
index d2216c74402e97b0724e3d702e6dc3cbecab2b6e..bd9f4f138e95e7394f0ffdda8bb3ba6e400b38e4 100644 (file)
@@ -140,7 +140,15 @@ ANN void gwion_end_child(const VM_Shred shred, const Gwion gwion) {
   if (gwion->data->child2.ptr) fork_clean2(shred, &gwion->data->child2);
 }
 
+ANN static inline void free_killed_shred(const Vector v) {
+  for (m_uint i = 0; i < vector_size(v); i++) {
+    const VM_Shred shred = (VM_Shred)vector_at(v, i);
+    free_vm_shred(shred);
+  }
+}
+
 ANN void gwion_end(const Gwion gwion) {
+  free_killed_shred(&gwion->vm->shreduler->killed_shreds);
   gwion_end_child(gwion->vm->cleaner_shred, gwion);
   free_env(gwion->env);
   if (gwion->vm->cleaner_shred) free_vm_shred(gwion->vm->cleaner_shred);
index cefac6004756d0b097496596a0d3a471d28fa1d3..6fb5beb33b5cbe7f2e79761b3aa26e70faf39615 100644 (file)
@@ -84,9 +84,10 @@ static MFUN(shred_yield) {
 static SFUN(vm_shred_from_id) {
   const m_int index = *(m_int *)MEM(0);
   if (index > 0) {
-    for (m_uint i = 0; i < vector_size(&shred->tick->shreduler->shreds); ++i) {
+    const Vector v = &shred->tick->shreduler->active_shreds;
+    for (m_uint i = 0; i < vector_size(v); ++i) {
       const VM_Shred s =
-          (VM_Shred)vector_at(&shred->tick->shreduler->shreds, i);
+          (VM_Shred)vector_at(v, i);
       if (s->tick->xid == (m_uint)index) {
         *(M_Object *)RETURN = s->info->me;
         return;
index 452b5a51438e7206f813f1058dca110ff574b248..bc8e5668b460f76dd1a41c84dd8658e2d6f4575e 100644 (file)
@@ -26,7 +26,7 @@ ANN VM_Shred shreduler_get(const Shreduler s) {
       return tk->self;
     }
   }
-  if (!s->loop && !vector_size(&s->shreds)) bbq->is_running = 0;
+  if (!s->loop && !vector_size(&s->active_shreds)) bbq->is_running = 0;
   MUTEX_UNLOCK(s->mutex);
   return NULL;
 }
@@ -42,7 +42,7 @@ ANN static void shreduler_erase(const Shreduler          s,
                                 struct ShredTick_ *const tk) {
   if (tk->parent) vector_rem2(&tk->parent->child, (vtype)tk->self);
   if (tk->child.ptr) shreduler_child(&tk->child);
-  vector_rem2(&s->shreds, (vtype)tk->self);
+  vector_rem2(&s->active_shreds, (vtype)tk->self);
 }
 
 ANN void shreduler_remove(const Shreduler s, const VM_Shred out,
@@ -99,6 +99,21 @@ ANN void shreduler_ini(const Shreduler s, const VM_Shred shred) {
 ANN void shreduler_add(const Shreduler s, const VM_Shred shred) {
   shreduler_ini(s, shred);
   shred->tick->xid = ++s->shred_ids;
-  vector_add(&s->shreds, (vtype)shred);
+  vector_add(&s->active_shreds, (vtype)shred);
   shredule(s, shred, GWION_EPSILON);
 }
+
+ANN Shreduler new_shreduler(const MemPool mp) {
+  Shreduler s = (Shreduler)mp_calloc(mp, Shreduler);
+  vector_init(&s->active_shreds);
+  vector_init(&s->killed_shreds);
+  MUTEX_SETUP(s->mutex);
+  return s;
+}
+
+ANN void free_shreduler(const MemPool mp, const Shreduler s) {
+  vector_release(&s->active_shreds);
+  vector_release(&s->killed_shreds);
+  MUTEX_CLEANUP(s->mutex);
+  mp_free(mp, Shreduler, s);
+}
index b857420318506f8f0344e73a5d3aae01cdc9d87c..31c23a392122d04e91aa59b4feb57dd7a3026fa3 100644 (file)
@@ -47,48 +47,68 @@ ANN static inline void shred_unwind(const VM_Shred shred) {
   shred->mem -= frame->push;
 }
 
-ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) {
+ANN static void clean_values(const VM_Shred shred) {
   const VM_Code code = shred->code;
-  if (code->live_values.ptr) {
-    const uint16_t pc = shred->pc;
-    for (m_uint i = 0; i < m_vector_size(&code->live_values); i++) {
-      VMValue *vmval = (VMValue *)m_vector_addr(&code->live_values, i);
-      if (pc <= vmval->start) break;
-      if (pc >= vmval->end) continue;
-      m_bit *const data = &*(m_bit *)(shred->mem + vmval->offset);
-      compound_release(shred, vmval->t, data);
-    }
+  const uint16_t pc = shred->pc;
+  for (m_uint i = 0; i < m_vector_size(&code->live_values); i++) {
+    VMValue *vmval = (VMValue *)m_vector_addr(&code->live_values, i);
+    if (pc <= vmval->start) break;
+    if (pc >= vmval->end) continue;
+    m_bit *const data = &*(m_bit *)(shred->mem + vmval->offset);
+    compound_release(shred, vmval->t, data);
   }
-  if (!size) return true;
-  if (code->handlers.ptr) {
-    const m_uint start = VKEY(&shred->info->frame, size - 1);
-    if (start > shred->pc) return true;
-    const Map m  = &code->handlers;
-    m_uint    pc = 0;
-    for (m_uint i = 0; i < map_size(m); i++) {
-      if (start > shred->pc) break;
-      if (start < shred->pc && VKEY(m, i) > shred->pc) {
-        const m_uint next  = VKEY(m, i);
-        const Instr  instr = (Instr)vector_at(&code->instr, next + 1);
-        if (!instr->m_val2 || (Symbol)instr->m_val2 == effect) {
-          pc = next + 1;
-          break;
-        }
-      }
+}
+
+ANN static uint16_t find_pc(const VM_Shred shred, const Symbol effect, const m_uint size) {
+  const VM_Code code = shred->code;
+  const m_uint start = VKEY(&shred->info->frame, size - 1);
+  if (start > shred->pc) return true;
+  const Map m  = &shred->code->handlers;
+  for (m_uint i = 0; i < map_size(m); i++) {
+    if (start > shred->pc) break;
+    if (start < shred->pc && VKEY(m, i) > shred->pc) {
+      const m_uint next  = VKEY(m, i);
+      const Instr  instr = (Instr)vector_at(&code->instr, next + 1);
+      if (!instr->m_val2 || (Symbol)instr->m_val2 == effect)
+        return next + 1;
     }
-    if (!pc) // outside of a try statement
-      return true;
-    shred->reg =
-        (m_bit *)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1);
-    shredule(shred->tick->shreduler, shred, 0);
-    shred->pc = pc; // VKEY(m, i);
-    // should we pop?
-    VLEN(&shred->info->frame) = size;
-    return false;
   }
-  // there might be no more stack to unwind
-  if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
-    return true;
+  return 0;
+}
+
+ANN static inline bool find_handle(const VM_Shred shred, const Symbol effect, const m_uint size) {
+  const m_uint start = VKEY(&shred->info->frame, size - 1);
+  if (start > shred->pc) return true;
+  const uint16_t pc = find_pc(shred, effect, size);
+  if (!pc) // outside of a try statement
+//    return true;
+    return false;
+  // we should clean values here
+  shred->reg = // restore reg
+      (m_bit *)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1);
+  shredule(shred->tick->shreduler, shred, 0);
+  shred->pc = pc; // VKEY(m, i);
+  vector_pop(&shred->info->frame);
+//  return false;
+  return true;
+}
+
+ANN static bool unwind(const VM_Shred shred, const Symbol effect, const m_uint size) {
+  const VM_Code code = shred->code;
+  if (code->live_values.ptr)
+    clean_values(shred);
+//  if (!size) return true;
+  if (!size) return false;
+  if (size) {
+    if (code->handlers.ptr)
+      return find_handle(shred, effect, size);
+    // there might be no more stack to unwind
+    if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
+//      return true;
+      return false;
+  } else
+//    return true;
+    return false;
   shred_unwind(shred);
   return unwind(shred, effect, size - 1);
 }
@@ -114,29 +134,55 @@ ANN static void trace(VM_Shred shred, const m_uint size) {
   trace(shred, i);
 }
 
+struct TraceStart {
+  const VM_Code code;
+  m_bit *const reg;
+  m_bit *const mem;
+};
+
+ANN static inline void shred_trace(const VM_Shred shred, const struct TraceStart *ts) {
+  shred->code = ts->code;
+  shred->reg  = ts->reg;
+  shred->mem  = ts->mem;
+  gw_err("\n{-/}here is the trace:\n");
+  trace(shred, vector_size(&shred->info->line));
+}
+
+ANN static inline void add_to_killed(const VM_Shred shred) {
+  const Shreduler shreduler = shred->tick->shreduler;
+  vector_rem2(&shreduler->active_shreds, (m_uint)shred);
+  vector_add(&shreduler->killed_shreds, (m_uint)shred);
+}
+
+ANN static inline void unhandled_pp(VM_Shred shred, const m_str effect) {
+  gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}: {-R}Unhandled {+R}%s{0}\n",
+         shred->tick->xid, effect);
+}
+
+ANN static inline void handle_fail(VM_Shred shred, const m_str effect, const struct TraceStart *ts) {
+  unhandled_pp(shred, effect);
+  if (shred->info->line.ptr) // trace if available
+    shred_trace(shred, ts);
+  add_to_killed(shred);
+}
+
 ANN void handle(VM_Shred shred, const m_str effect) {
-  m_bit *const reg = shred->reg;
-  m_bit *const mem = shred->mem;
+  shreduler_remove(shred->tick->shreduler, shred, false);
+  // store trace info
+  struct TraceStart ts = {
+    .code = shred->code,
+    .reg  = shred->reg,
+    .mem  = shred->mem
+  };
   const m_uint size =
       shred->info->frame.ptr ? vector_size(&shred->info->frame) : 0;
-  const VM_Code code = shred->code;
-  shreduler_remove(shred->tick->shreduler, shred, false);
+  // maybe we should use a string to avoid the insert_symbol call
   if (!unwind(shred, insert_symbol(shred->info->vm->gwion->st, effect), size))
-    return;
-  gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}: {-R}Unhandled {+R}%s{0}\n",
-         shred->tick->xid, effect);
-  if (shred->info->line.ptr) { // trace if available
-    shred->reg  = reg;
-    shred->mem  = mem;
-    shred->code = code;
-    gw_err("\n{-/}here is the trace:\n");
-    trace(shred, vector_size(&shred->info->line));
-  }
-  vm_shred_exit(shred);
+    handle_fail(shred, effect, &ts);
 }
 
 ANN bool vm_remove(const VM *vm, const m_uint index) {
-  const Vector v = (Vector)&vm->shreduler->shreds;
+  const Vector v = (Vector)&vm->shreduler->active_shreds;
   LOOP_OPTIM
   for (m_uint i = vector_size(v) + 1; --i;) {
     const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
@@ -148,15 +194,6 @@ ANN bool vm_remove(const VM *vm, const m_uint index) {
   return false;
 }
 
-ANN void free_vm(VM *vm) {
-  vector_release(&vm->shreduler->shreds);
-  vector_release(&vm->ugen);
-  if (vm->bbq) free_driver(vm->bbq, vm);
-  MUTEX_CLEANUP(vm->shreduler->mutex);
-  mp_free(vm->gwion->mp, Shreduler, vm->shreduler);
-  mp_free(vm->gwion->mp, VM, vm);
-}
-
 ANN void vm_add_shred(const VM *vm, const VM_Shred shred) {
   shred->info->vm = (VM *)vm;
   shred->info->me = new_shred(shred);
@@ -1257,11 +1294,13 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto]
   }
 }
 
+// remove me
 ANN void next_bbq_pos(const VM *vm) {
   Driver *const di = vm->bbq;
   if(++di->pos == 16777216-1) {
-    for(m_uint i = 0; i < vector_size(&vm->shreduler->shreds); i++) {
-      const VM_Shred shred = (VM_Shred)vector_at(&vm->shreduler->shreds, i);
+    const Vector v = &vm->shreduler->active_shreds;
+    for(m_uint i = 0; i < vector_size(v); i++) {
+      const VM_Shred shred = (VM_Shred)vector_at(v, i);
       shred->tick->wake_time -= 16777216.0;
     }
     di->pos = 0;
@@ -1276,12 +1315,11 @@ static void vm_run_audio(const VM *vm) {
 VM *new_vm(MemPool p, const bool audio) {
   VM *vm = (VM *)mp_calloc(p, VM);
   vector_init(&vm->ugen);
-  vm->bbq       = new_driver(p);
-  vm->bbq->run  = audio ? vm_run_audio : vm_run;
-  vm->shreduler = (Shreduler)mp_calloc(p, Shreduler);
-  vector_init(&vm->shreduler->shreds);
-  MUTEX_SETUP(vm->shreduler->mutex);
-  vm->shreduler->bbq = vm->bbq;
+  vm->shreduler = new_shreduler(p);
+  vm->bbq       = vm->shreduler->bbq = new_driver(p);
+  vm->bbq->run  = audio
+    ? vm_run_audio
+    : vm_run;
 #ifndef __AFL_COMPILER
   gw_seed(vm->rand, (uint64_t)time(NULL));
 #else
@@ -1289,3 +1327,11 @@ VM *new_vm(MemPool p, const bool audio) {
 #endif
   return vm;
 }
+
+ANN void free_vm(VM *vm) {
+  const MemPool mp = vm->gwion->mp;
+  free_shreduler(mp, vm->shreduler);
+  if (vm->bbq) free_driver(vm->bbq, vm);
+  vector_release(&vm->ugen);
+  mp_free(mp, VM, vm);
+}