aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ejit/ejit.h15
-rw-r--r--src/common.h9
-rw-r--r--src/compile/compile.c31
-rw-r--r--src/ejit.c79
-rw-r--r--src/interp.c105
5 files changed, 74 insertions, 165 deletions
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h
index 4ab2bbc..48c4dda 100644
--- a/include/ejit/ejit.h
+++ b/include/ejit/ejit.h
@@ -223,21 +223,6 @@ double ejit_run_func_d(struct ejit_func *f, size_t argc,
struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]);
-
-/* currently unused, the idea is that an escape could get the interpreter state
- * and pass it on to speed up entering/exiting the VM, could be useful for more
- * dynamic languages */
-struct interp_state;
-
-long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx);
-
-
void ejit_destroy_func(struct ejit_func *s);
#define EJIT_GPR(x) ((struct ejit_gpr){.r = (x)})
diff --git a/src/common.h b/src/common.h
index 6ee0df7..493a89d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -288,13 +288,7 @@ struct ejit_func {
void *direct_call;
size_t size;
size_t prio;
-};
-
-
-struct interp_state {
- struct gprs gprs;
- struct fprs fprs;
- struct args args;
+ size_t max_args;
};
union interp_ret {
@@ -304,7 +298,6 @@ union interp_ret {
union interp_ret ejit_run(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc],
- struct interp_state *state,
bool run,
void ***labels_wb);
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 490bc43..c979305 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -19,6 +19,27 @@ struct reloc_helper {
#define VEC_NAME addrs
#include "../vec.h"
+/* skip assertions since we know they must be valid due to type checking earlier */
+static long checked_run_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, true, NULL).i;
+}
+
+static int64_t checked_run_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, true, NULL).i;
+}
+
+static float checked_run_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, true, NULL).f;
+}
+
+static double checked_run_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ return ejit_run(f, argc, args, true, NULL).f;
+}
+
static void *alloc_arena(size_t size, bool im_scawed)
{
return mmap(NULL, size,
@@ -2217,15 +2238,15 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case CALLI_L:
#if __WORDSIZE == 64
- call = ejit_run_func_l; goto calli;
+ call = checked_run_l; goto calli;
#else
assert(0 && "trying to compile calli_l on 32bit arch");
break;
#endif
- case CALLI_F: { call = ejit_run_func_f; goto calli; }
- case CALLI_D: { call = ejit_run_func_d; goto calli; }
- case CALLI_I: { call = ejit_run_func_i; goto calli;
+ case CALLI_F: { call = checked_run_f; goto calli; }
+ case CALLI_D: { call = checked_run_d; goto calli; }
+ case CALLI_I: { call = checked_run_i; goto calli;
calli:
save_caller_save_regs(f, j);
@@ -2425,7 +2446,7 @@ static size_t align_up(size_t a, size_t n)
bool ejit_compile(struct ejit_func *f, bool use_64, bool im_scawed)
{
(void)use_64;
-#if __WORDSIZE == 32
+#if __WORDSIZE != 64
/* can't compile 64bit code on 32bit systems, give up early */
if (use_64)
return false;
diff --git a/src/ejit.c b/src/ejit.c
index 265acea..0a0e7a1 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -339,6 +339,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc,
f->size = 0;
f->prio = 1;
f->use_64 = false;
+ f->max_args = 0;
for (size_t i = 0; i < argc; ++i) {
types_append(&f->sign, args[i].type);
@@ -403,7 +404,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr,
void **labels;
/* just get labels, don't actually run anything yet */
- ejit_run(f, 0, NULL, NULL, false, &labels);
+ ejit_run(f, 0, NULL, false, &labels);
foreach_vec(ii, f->insns) {
struct ejit_insn i = *insns_at(&f->insns, ii);
@@ -448,6 +449,7 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l)
void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
+ f->max_args = argc > f->max_args ? argc : f->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -467,6 +469,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
s->use_64 = true;
+ f->max_args = argc > f->max_args ? argc : f->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -485,6 +488,7 @@ void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc,
void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -503,6 +507,7 @@ void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->max_args = argc > s->max_args ? argc : s->max_args;
check_operands(f, argc, args);
for (size_t i = 0; i < argc; ++i) {
@@ -521,6 +526,7 @@ void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -538,6 +544,7 @@ void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
const struct ejit_operand args[argc])
{
s->use_64 = true;
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -554,6 +561,7 @@ void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -570,6 +578,7 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->max_args = argc > s->max_args ? argc : s->max_args;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -1647,23 +1656,8 @@ struct ejit_reloc ejit_bmsr(struct ejit_func *s, struct ejit_gpr r0,
return (struct ejit_reloc){.insn = addr};
}
-static struct interp_state create_interp_state()
-{
- struct interp_state state;
- state.gprs = gprs_create();
- state.fprs = fprs_create();
- state.args = args_create();
- return state;
-}
-
-static void destroy_interp_state(struct interp_state state)
-{
- gprs_destroy(&state.gprs);
- fprs_destroy(&state.fprs);
- args_destroy(&state.args);
-}
-
-long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+long ejit_run_func_i(struct ejit_func *f, size_t argc,
+ struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert((f->rtype == EJIT_VOID || ejit_int_type(f->rtype))
@@ -1672,64 +1666,29 @@ long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[
#endif
);
- return ejit_run(f, argc, args, ctx, true, NULL).i;
+ return ejit_run(f, argc, args, true, NULL).i;
}
-long ejit_run_func_i(struct ejit_func *f, size_t argc,
+int64_t ejit_run_func_l(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc])
{
- struct interp_state state = create_interp_state();
- long r = ejit_run_func_ctx_i(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
-}
-
-int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
-{
check_args(f, argc, args);
assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64);
- return ejit_run(f, argc, args, ctx, true, NULL).i;
-}
-
-int64_t ejit_run_func_l(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- int64_t r = ejit_run_func_ctx_l(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
+ return ejit_run(f, argc, args, true, NULL).i;
}
-float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert(f->rtype == EJIT_FLOAT);
- return ejit_run(f, argc, args, ctx, true, NULL).f;
+ return ejit_run(f, argc, args, true, NULL).f;
}
-float ejit_run_func_f(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- float r = ejit_run_func_ctx_f(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
-}
-
-double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
{
check_args(f, argc, args);
assert(f->rtype == EJIT_DOUBLE);
- return ejit_run(f, argc, args, ctx, true, NULL).f;
-}
-
-double ejit_run_func_d(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc])
-{
- struct interp_state state = create_interp_state();
- double r = ejit_run_func_ctx_d(f, argc, args, &state);
- destroy_interp_state(state);
- return r;
+ return ejit_run(f, argc, args, true, NULL).f;
}
struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
diff --git a/src/interp.c b/src/interp.c
index f8ba927..80a9edc 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -5,7 +5,7 @@
/* this is the body of a given ejit_interp function, it assumes there's an
* external int64_t retval and double retval_f into which it places the value to
* be returned. Included from src/interp.c */
-union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb)
+union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], bool run, void ***labels_wb)
{
static void *labels[OPCODE_COUNT] = {
[MOVI] = &&MOVI,
@@ -227,40 +227,35 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
if (f->arena) {
if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64)
return (union interp_ret){
- .i = ((ejit_escape_l_t)f->arena)(argc, args)
+ .i = ((ejit_escape_l_t)f->arena)(paramc, params)
};
if (f->rtype == EJIT_DOUBLE)
return (union interp_ret){
- .f = ((ejit_escape_d_t)f->arena)(argc, args)
+ .f = ((ejit_escape_d_t)f->arena)(paramc, params)
};
if (f->rtype == EJIT_FLOAT)
return (union interp_ret){
- .f = ((ejit_escape_f_t)f->arena)(argc, args)
+ .f = ((ejit_escape_f_t)f->arena)(paramc, params)
};
return (union interp_ret){
- .i = ((ejit_escape_i_t)f->arena)(argc, args)
+ .i = ((ejit_escape_i_t)f->arena)(paramc, params)
};
}
int64_t retval = 0; double retval_f = 0.0;
- size_t prev_gprs = gprs_len(&state->gprs);
- size_t prev_fprs = fprs_len(&state->fprs);
- size_t prev_argc = args_len(&state->args);
-
- gprs_reserve(&state->gprs, prev_gprs + gpr_stats_len(&f->gpr));
- fprs_reserve(&state->fprs, prev_fprs + fpr_stats_len(&f->fpr));
-
union fpr {
double d;
float f;
};
- int64_t *gpr = ((int64_t *)state->gprs.buf) + prev_gprs;
- union fpr *fpr = ((union fpr *)state->fprs.buf) + prev_fprs;
+ size_t argc = 0;
+ int64_t *gpr = alloca(sizeof(int64_t) * gpr_stats_len(&f->gpr));
+ union fpr *fpr = alloca(sizeof(int64_t) * fpr_stats_len(&f->fpr));
+ struct ejit_arg *args = alloca(sizeof(struct ejit_arg) * f->max_args);
struct ejit_insn *insns = f->insns.buf;
/* retval is kind of an unfortunate extra bit of state to keep track of,
@@ -978,25 +973,25 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
DISPATCH();
DO(PARAM);
- gpr[i.r2] = args[i.r0].u64;
+ gpr[i.r2] = params[i.r0].u64;
DISPATCH();
DO(PARAM_F);
if (i.r1 == EJIT_FLOAT)
- fpr[i.r2].f = args[i.r0].f;
+ fpr[i.r2].f = params[i.r0].f;
else
- fpr[i.r2].d = args[i.r0].d;
+ fpr[i.r2].d = params[i.r0].d;
DISPATCH();
DO(ARG);
struct ejit_arg a = ejit_build_arg(i.r1, gpr[i.r2]);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_I);
struct ejit_arg a = ejit_build_arg(i.r1, i.o);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_F);
@@ -1006,7 +1001,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
else
a = ejit_build_arg_f(i.r1, fpr[i.r2].f);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(ARG_FI);
@@ -1016,95 +1011,55 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
else
a = ejit_build_arg_f(i.r1, i.f);
- args_append(&state->args, a);
+ args[argc++] = a;
DISPATCH();
DO(CALLI_I);
struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval = ejit_run(f, argc, args, state, true, NULL).i;
-
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ retval = ejit_run(f, argc, args, true, NULL).i;
+ argc = 0;
DISPATCH();
DO(CALLI_L);
struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval = ejit_run(f, argc, args, state, true, NULL).i;
-
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ retval = ejit_run(f, argc, args, true, NULL).i;
+ argc = 0;
DISPATCH();
DO(CALLI_F);
struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval_f = ejit_run(f, argc, args, state, true, NULL).f;
-
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ retval_f = ejit_run(f, argc, args, true, NULL).f;
+ argc = 0;
DISPATCH();
DO(CALLI_D);
struct ejit_func *f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
- retval_f = ejit_run(f, argc, args, state, true, NULL).f;
-
- gpr = state->gprs.buf + prev_gprs;
- fpr = (union fpr *)state->fprs.buf + prev_fprs;
- args_shrink(&state->args, prev_argc);
+ retval_f = ejit_run(f, argc, args, true, NULL).f;
+ argc = 0;
DISPATCH();
DO(ESCAPEI_I);
ejit_escape_i_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
retval = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_L);
ejit_escape_l_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
retval = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_F);
ejit_escape_f_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
retval_f = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ argc = 0;
DISPATCH();
DO(ESCAPEI_D);
ejit_escape_d_t f = i.p;
- size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = state->args.buf + prev_argc;
-
retval_f = f(argc, args);
-
- args_shrink(&state->args, prev_argc);
+ argc = 0;
DISPATCH();
/* dispatch is technically unnecessary for returns, but keep it for
@@ -1144,13 +1099,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args
#undef DO
out_float:
- gprs_shrink(&state->gprs, prev_gprs);
- fprs_shrink(&state->fprs, prev_fprs);
return (union interp_ret){.f = retval_f};
out_int:
- gprs_shrink(&state->gprs, prev_gprs);
- fprs_shrink(&state->fprs, prev_fprs);
return (union interp_ret){.i = retval};
zero_out: