aboutsummaryrefslogtreecommitdiff
path: root/src/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp.c')
-rw-r--r--src/interp.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/src/interp.c b/src/interp.c
index 25f723a..ed7e59c 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -2,7 +2,7 @@
#include "common.h"
-union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], bool run, void ***labels_wb)
+union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb)
{
static void *labels[OPCODE_COUNT] = {
[MOVI] = &&MOVI,
@@ -61,10 +61,16 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
return (union interp_ret){.r = 0};
}
- long *gpr = malloc(f->gpr * sizeof(long));
- double *fpr = malloc(f->fpr * sizeof(double));
+ size_t prev_gprs = vec_len(&state->gprs);
+ size_t prev_fprs = vec_len(&state->fprs);
+ size_t prev_argc = vec_len(&state->args);
+
+ vec_reserve(&state->gprs, prev_gprs + f->gpr);
+ vec_reserve(&state->fprs, prev_fprs + f->fpr);
+
+ long *gpr = ((long *)state->gprs.buf) + prev_gprs;
+ double *fpr = ((double *)state->fprs.buf) + prev_fprs;
- struct vec call_args = vec_create(sizeof(struct ejit_arg));
struct ejit_insn *insns = f->insns.buf;
/* retval is kind of an unfortunate extra bit of state to keep track of,
@@ -190,40 +196,47 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
DO(ARG);
struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]);
- vec_append(&call_args, &a);
+ vec_append(&state->args, &a);
DISPATCH();
DO(ARG_I);
struct ejit_arg a = ejit_build_arg(i.r1, i.o);
- vec_append(&call_args, &a);
+ vec_append(&state->args, &a);
DISPATCH();
DO(ARG_F);
struct ejit_arg a = ejit_build_arg_f(i.r1, fpr[i.r2]);
- vec_append(&call_args, &a);
+ vec_append(&state->args, &a);
DISPATCH();
DO(ARG_FI);
struct ejit_arg a = ejit_build_arg_f(i.r1, i.d);
- vec_append(&call_args, &a);
+ vec_append(&state->args, &a);
DISPATCH();
DO(CALLI);
struct ejit_func *f = i.p;
- retval = ejit_run_func(f, vec_len(&call_args), call_args.buf);
- vec_reset(&call_args);
+ size_t argc = vec_len(&state->args) - prev_argc;
+ struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + prev_argc;
+
+ retval = ejit_run_interp(f, argc, args, state);
+
+ gpr = ((long *)state->gprs.buf) + prev_gprs;
+ fpr = ((double *)state->fprs.buf) + prev_fprs;
+ vec_shrink(&state->args, prev_argc);
DISPATCH();
DO(CALLI_F);
- struct ejit_func *f = i.p;
- retval_f = ejit_run_func_f(f, vec_len(&call_args), call_args.buf);
- vec_reset(&call_args);
DISPATCH();
DO(ESCAPEI);
ejit_escape_t f = i.p;
- retval = f(vec_len(&call_args), call_args.buf);
- vec_reset(&call_args);
+ size_t argc = vec_len(&state->args) - prev_argc;
+ struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) + prev_argc;
+
+ retval = f(argc, args);
+
+ vec_shrink(&state->args, prev_argc);
DISPATCH();
/* dispatch is technically unnecessary for returns, but keep it for
@@ -253,14 +266,12 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a
#undef DO
out_int:
- free(gpr);
- free(fpr);
- vec_destroy(&call_args);
+ vec_shrink(&state->gprs, prev_gprs);
+ vec_shrink(&state->fprs, prev_fprs);
return (union interp_ret){.r = retval};
out_float:
- free(gpr);
- free(fpr);
- vec_destroy(&call_args);
+ vec_shrink(&state->gprs, prev_gprs);
+ vec_shrink(&state->fprs, prev_fprs);
return (union interp_ret){.d = retval_f};
}