diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-08-12 00:19:50 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-08-12 01:03:00 +0200 |
commit | 47528f02e7376f1fbb205c5cf69d17d55619fcb1 (patch) | |
tree | 4a6255f3c741cbcbb33b42605177e200122e1ff2 /vm.c | |
parent | 381cc7508f797e5158bbd1620d6154ef4a11b76c (diff) |
vm: support automatic periodic GC runs
Introduce two new VM api functions uc_vm_gc_start() and uc_vm_gc_stop()
which allow starting and stopping automatic periodic garbage collection
of cyclic objects in the VM context.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 59 |
1 files changed, 59 insertions, 0 deletions
@@ -2508,6 +2508,35 @@ uc_vm_insn_dynload(uc_vm_t *vm, uc_vm_insn_t insn) } } +static void +uc_vm_gc_step(uc_vm_t *vm) +{ + size_t curr_count = 0, prev_count = 0; + uc_weakref_t *ref; + + if (!(vm->gc_flags & GC_ENABLED)) + return; + + if (vm->alloc_refs >= vm->gc_interval) { + if (vm->trace) { + for (ref = vm->values.next; ref != &vm->values; ref = ref->next) + prev_count++; + + ucv_gc(vm); + + for (ref = vm->values.next; ref != &vm->values; ref = ref->next) + curr_count++; + + fprintf(stderr, "! GC reclaimed %zu object(s)\n", prev_count - curr_count); + } + else { + ucv_gc(vm); + } + + vm->alloc_refs = 0; + } +} + static uc_value_t * uc_vm_callframe_pop(uc_vm_t *vm) { @@ -2755,6 +2784,7 @@ uc_vm_execute_chunk(uc_vm_t *vm) case I_POP: ucv_put(uc_vm_stack_pop(vm)); + uc_vm_gc_step(vm); break; case I_CUPV: @@ -3028,3 +3058,32 @@ uc_vm_registry_delete(uc_vm_t *vm, const char *key) { return ucv_object_delete(vm->registry, key); } + +bool +uc_vm_gc_start(uc_vm_t *vm, uint16_t interval) +{ + bool changed = false; + + if (vm->gc_interval != interval) { + vm->gc_interval = interval; + changed = true; + } + + if (!(vm->gc_flags & GC_ENABLED)) { + vm->gc_flags |= GC_ENABLED; + changed = true; + } + + return changed; +} + +bool +uc_vm_gc_stop(uc_vm_t *vm) +{ + if (!(vm->gc_flags & GC_ENABLED)) + return false; + + vm->gc_flags &= ~GC_ENABLED; + + return true; +} |