From 85d7885e226ed79dc071e0cef73ccc918144a8f5 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 00:22:26 +0200 Subject: lib: implement gc() Introduce a new stdlib function `gc()` which allows controlling the periodic garbage collector from ucode. Signed-off-by: Jo-Philipp Wich --- tests/custom/03_stdlib/60_gc | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 tests/custom/03_stdlib/60_gc (limited to 'tests') diff --git a/tests/custom/03_stdlib/60_gc b/tests/custom/03_stdlib/60_gc new file mode 100644 index 0000000..44e5d9e --- /dev/null +++ b/tests/custom/03_stdlib/60_gc @@ -0,0 +1,107 @@ +The `gc()` function allows controlling the garbage collector of the VM. +It takes the requested operation as first argument and an optional, +operation specific second argument. + +Returns `null` if the given operation is invalid or if the operation +specific argument is invalid. + +Returns `false` if the requested operation would not result in any +changes. + +Returns `true` if the requested oepration succeeded (e.g. starting +the GC when it was previously stopped). + +Returns an object count if the given operation is `count`. + +-- Testcase -- +{% + printf("Count #1: %d\n", gc("count")); + + // create an unreachable cyclic structure + let o = {}; + o.cycle = o; + o = null; + + printf("Count #2: %d\n", gc("count")); + + // invoking gc without any argument defaults to "collect" + gc(); + + printf("Count #3: %d\n", gc("count")); + + + // create another unreachable cyclic structure + o = {}; + o.cycle = o; + o = null; + + printf("Count #4: %d\n", gc("count")); + + // invoking gc with explicit collect argument + gc("collect"); + + printf("Count #5: %d\n", gc("count")); +%} +-- End -- + +-- Expect stdout -- +Count #1: 5 +Count #2: 6 +Count #3: 5 +Count #4: 6 +Count #5: 5 +-- End -- + + +Testing enabling the automatic collector. + +-- Testcase -- +{% + // start GC, trigger every 10 object allocations + gc("start", 10); + + for (let i = 0; i < 100; i++) { + let o = {}; + o.cyle = o; + o = null; + + if ((i % 10) == 0) + printf("Count #%d: %d\n", (i / 10) + 1, gc("count")); + } + + // stop GC + gc("stop"); + + for (let i = 100; i < 200; i++) { + let o = {}; + o.cyle = o; + o = null; + + if ((i % 10) == 0) + printf("Count #%d: %d\n", (i / 10) + 1, gc("count")); + } +%} +-- End -- + +-- Expect stdout -- +Count #1: 6 +Count #2: 12 +Count #3: 12 +Count #4: 12 +Count #5: 12 +Count #6: 12 +Count #7: 12 +Count #8: 12 +Count #9: 12 +Count #10: 12 +Count #11: 12 +Count #12: 22 +Count #13: 32 +Count #14: 42 +Count #15: 52 +Count #16: 62 +Count #17: 72 +Count #18: 82 +Count #19: 92 +Count #20: 102 +-- End -- -- cgit v1.2.3 From b41cb2d7b7cc1a10f4f68f9c8f544f916f448822 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 12 Aug 2022 00:54:27 +0200 Subject: main: introduce -g flag to allow enabling periodic gc from cli Implement a new flag `-g` which takes an interval value and enables the periodic GC with the given interval for cyclic object structures in the VM if specified. Signed-off-by: Jo-Philipp Wich --- main.c | 13 ++++++++++++- tests/cram/test_basic.t | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/main.c b/main.c index 02df3b1..03549fe 100644 --- a/main.c +++ b/main.c @@ -54,6 +54,10 @@ print_usage(const char *app) "-t\n" " Enable VM execution tracing.\n\n" + "-g interval\n" + " Perform periodic garbage collection every `interval` object\n" + " allocations.\n\n" + "-S\n" " Enable strict mode.\n\n" @@ -130,6 +134,9 @@ compile(uc_vm_t *vm, uc_source_t *src, FILE *precompile, bool strip, char *inter goto out; } + if (vm->gc_interval) + uc_vm_gc_start(vm, vm->gc_interval); + rc = uc_vm_execute(vm, program, &res); switch (rc) { @@ -468,7 +475,7 @@ appname(const char *argv0) int main(int argc, char **argv) { - const char *optspec = "he:tST::RD:F:U:l:L:c::o:s"; + const char *optspec = "he:tg:ST::RD:F:U:l:L:c::o:s"; char *interp = "/usr/bin/env ucode"; uc_source_t *source = NULL; FILE *precompile = NULL; @@ -554,6 +561,10 @@ main(int argc, char **argv) uc_vm_trace_set(&vm, 1); break; + case 'g': + vm.gc_interval = atoi(optarg); + break; + case 'D': if (!parse_define_string(optarg, uc_vm_scope_get(&vm))) { rv = 1; diff --git a/tests/cram/test_basic.t b/tests/cram/test_basic.t index 5911ac9..c33dee9 100644 --- a/tests/cram/test_basic.t +++ b/tests/cram/test_basic.t @@ -25,6 +25,10 @@ check that ucode provides exepected help: -t Enable VM execution tracing. + -g interval + Perform periodic garbage collection every `interval` object + allocations. + -S Enable strict mode. -- cgit v1.2.3