diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-02-06 00:12:48 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-02-07 00:04:35 +0100 |
commit | 3a49192f3a1e8a5d348cdbfccd0a16d74ba61e3d (patch) | |
tree | 6d8a4b620b362ab4f707678a5b626a85e1531c0b /program.c | |
parent | 5bd764a35aeaf50b54957bfa94ba94198514baf0 (diff) |
treewide: rework function memory model
- Instead of treating individual program functions as managed ucode types,
demote uc_function_t values to pointers into a uc_program_t entity
- Promote uc_program_t to a managed type
- Let uc_closure_t claim references to the owning program of the enclosed
uc_function_t
- Redefine public APIs uc_compile() and uc_vm_execute() APIs to return and
expect an uc_program_t object respectively
- Remove vallist indirection for function loading and let the compiler
emit the function id directly when producing function construction code
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'program.c')
-rw-r--r-- | program.c | 118 |
1 files changed, 63 insertions, 55 deletions
@@ -21,6 +21,7 @@ #include "ucode/program.h" #include "ucode/source.h" #include "ucode/vallist.h" +#include "ucode/chunk.h" uc_program_t * @@ -30,6 +31,9 @@ uc_program_new(uc_source_t *source) prog = xalloc(sizeof(*prog)); + prog->header.type = UC_PROGRAM; + prog->header.refcount = 1; + prog->functions.next = &prog->functions; prog->functions.prev = &prog->functions; @@ -40,80 +44,83 @@ uc_program_new(uc_source_t *source) return prog; } -static inline uc_function_t * -ref_to_function(uc_weakref_t *ref) -{ - return (uc_function_t *)((uintptr_t)ref - offsetof(uc_function_t, progref)); -} - -static inline uc_value_t * -ref_to_uv(uc_weakref_t *ref) -{ - return (uc_value_t *)((uintptr_t)ref - offsetof(uc_function_t, progref)); -} - -void -uc_program_free(uc_program_t *prog) +uc_function_t * +uc_program_function_new(uc_program_t *prog, const char *name, size_t srcpos) { - uc_weakref_t *ref, *tmp; uc_function_t *func; + size_t namelen = 0; - if (!prog) - return; + if (name) + namelen = strlen(name); - for (ref = prog->functions.next, tmp = ref->next; ref != &prog->functions; ref = tmp, tmp = tmp->next) { - func = ref_to_function(ref); - func->program = NULL; - func->progref.next = NULL; - func->progref.prev = NULL; + func = xalloc(sizeof(*func) + namelen + 1); - ucv_put(&func->header); - } - - uc_vallist_free(&prog->constants); - uc_source_put(prog->source); - free(prog); -} - -uc_value_t * -uc_program_function_new(uc_program_t *prog, const char *name, size_t srcpos) -{ - uc_function_t *func; + if (name) + strcpy(func->name, name); - func = (uc_function_t *)ucv_function_new(name, srcpos, prog); - func->root = (prog->functions.next == &prog->functions); + func->nargs = 0; + func->nupvals = 0; + func->srcpos = srcpos; + func->program = prog; + func->vararg = false; + uc_chunk_init(&func->chunk); ucv_ref(&prog->functions, &func->progref); - return &func->header; + return func; } size_t -uc_program_function_id(uc_program_t *prog, uc_value_t *func) +uc_program_function_id(uc_program_t *prog, uc_function_t *func) { - uc_weakref_t *ref; - size_t i; + size_t i = 1; - for (ref = prog->functions.prev, i = 1; ref != &prog->functions; ref = ref->prev, i++) - if (ref_to_uv(ref) == func) + uc_program_function_foreach(prog, fn) { + if (fn == func) return i; + i++; + } + return 0; } -uc_value_t * +uc_function_t * uc_program_function_load(uc_program_t *prog, size_t id) { - uc_weakref_t *ref; - size_t i; + size_t i = 1; - for (ref = prog->functions.prev, i = 1; ref != &prog->functions; ref = ref->prev, i++) - if (i == id) - return ref_to_uv(ref); + uc_program_function_foreach(prog, fn) + if (i++ == id) + return fn; return NULL; } +size_t +uc_program_function_srcpos(uc_function_t *fn, size_t off) +{ + size_t pos; + + if (!fn) + return 0; + + pos = uc_chunk_debug_get_srcpos(&fn->chunk, off); + + return pos ? fn->srcpos + pos : 0; +} + +void +uc_program_function_free(uc_function_t *func) +{ + if (!func) + return; + + ucv_unref(&func->progref); + uc_chunk_free(&func->chunk); + free(func); +} + uc_value_t * uc_program_get_constant(uc_program_t *prog, size_t idx) { @@ -295,8 +302,7 @@ void uc_program_write(uc_program_t *prog, FILE *file, bool debug) { uint32_t flags = 0; - uc_weakref_t *ref; - size_t i; + size_t i = 0; if (debug) flags |= UC_PROGRAM_F_DEBUG; @@ -328,13 +334,15 @@ uc_program_write(uc_program_t *prog, FILE *file, bool debug) write_vallist(&prog->constants, file); /* write program sections */ - for (i = 0, ref = prog->functions.prev; ref != &prog->functions; ref = ref->prev) + uc_program_function_foreach(prog, fn1) { + (void)fn1; i++; + } write_u32(i, file); - for (ref = prog->functions.prev; ref != &prog->functions; ref = ref->prev) - write_function(ref_to_function(ref), file, debug); + uc_program_function_foreach(prog, fn2) + write_function(fn2, file, debug); } static bool @@ -779,7 +787,7 @@ uc_program_load(uc_source_t *input, char **errp) return program; out: - uc_program_free(program); + uc_program_put(program); return NULL; } @@ -790,5 +798,5 @@ uc_program_entry(uc_program_t *program) if (program->functions.prev == &program->functions) return NULL; - return ref_to_function(program->functions.prev); + return (uc_function_t *)program->functions.prev; } |