summaryrefslogtreecommitdiffhomepage
path: root/program.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-02-06 00:12:48 +0100
committerJo-Philipp Wich <jo@mein.io>2022-02-07 00:04:35 +0100
commit3a49192f3a1e8a5d348cdbfccd0a16d74ba61e3d (patch)
tree6d8a4b620b362ab4f707678a5b626a85e1531c0b /program.c
parent5bd764a35aeaf50b54957bfa94ba94198514baf0 (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.c118
1 files changed, 63 insertions, 55 deletions
diff --git a/program.c b/program.c
index de7e747..1810b06 100644
--- a/program.c
+++ b/program.c
@@ -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;
}