From 47528f02e7376f1fbb205c5cf69d17d55619fcb1 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 00:19:50 +0200 Subject: 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 --- vm.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'vm.c') diff --git a/vm.c b/vm.c index c08f9ce..d8f0074 100644 --- a/vm.c +++ b/vm.c @@ -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; +} -- cgit v1.2.3