diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-28 19:33:03 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-28 19:33:03 +0300 |
commit | 29718f2e84478b296c3198ae6d35cfd5d79efb14 (patch) | |
tree | 5261fe6e369f27f66a48c6f307870fc854c693c8 /src/ejit.c | |
parent | 2fc4f728643f78577c26e548619bc7db90a7c6ae (diff) | |
download | ejit-29718f2e84478b296c3198ae6d35cfd5d79efb14.tar.gz ejit-29718f2e84478b296c3198ae6d35cfd5d79efb14.zip |
optimize interpreter a bit
+ Use a gpr/fpr/arg stack shared between different functions to minimize
amount of memory allocations done at runtime while still allowing
interleaving bytecode/machine code functions during call, just with a
bit of extra setup in between
Diffstat (limited to 'src/ejit.c')
-rw-r--r-- | src/ejit.c | 38 |
1 files changed, 35 insertions, 3 deletions
@@ -74,7 +74,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, bool void **labels; /* just get labels, don't actually run anything yet */ - ejit_interp(f, 0, NULL, false, &labels); + ejit_interp(f, 0, NULL, NULL, false, &labels); foreach_vec(ii, f->insns) { struct ejit_insn i = vect_at(struct ejit_insn, f->insns, ii); void *addr = labels[i.op]; @@ -292,6 +292,32 @@ struct ejit_reloc ejit_jmp(struct ejit_func *s) return (struct ejit_reloc){.insn = addr}; } +static struct interp_state create_interp_state() +{ + struct interp_state state; + state.gprs = vec_create(sizeof(long)); + state.gprs = vec_create(sizeof(double)); + state.args = vec_create(sizeof(struct ejit_arg)); + return state; +} + +static void destroy_interp_state(struct interp_state state) +{ + vec_destroy(&state.gprs); + vec_destroy(&state.fprs); + vec_destroy(&state.args); +} + +long ejit_run_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state) +{ + assert(f->gpr && "trying to run a function that hasn't been compiled"); + assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype)); + if (f->arena) + return ((ejit_escape_t)f->arena)(argc, args); + + return ejit_interp(f, argc, args, state, true, NULL).r; +} + long ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { assert(f->gpr && "trying to run a function that hasn't been compiled"); @@ -299,7 +325,10 @@ long ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) if (f->arena) return ((ejit_escape_t)f->arena)(argc, args); - return ejit_interp(f, argc, args, true, NULL).r; + struct interp_state state = create_interp_state(); + long r = ejit_interp(f, argc, args, &state, true, NULL).r; + destroy_interp_state(state); + return r; } double ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) @@ -309,5 +338,8 @@ double ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[ar if (f->arena) return ((ejit_escape_f_t)f->arena)(argc, args); - return ejit_interp(f, argc, args, true, NULL).d; + struct interp_state state = create_interp_state(); + double r = ejit_interp(f, argc, args, &state, true, NULL).d; + destroy_interp_state(state); + return r; } |