Skip to content

Commit

Permalink
simplify execute api a bit
Browse files Browse the repository at this point in the history
by making parameter push and result pop explicit.
  • Loading branch information
yamt committed Jul 10, 2023
1 parent 67412fc commit 4afd257
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 122 deletions.
8 changes: 7 additions & 1 deletion cli/repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,11 @@ exec_func(struct exec_context *ctx, uint32_t funcidx,
*/
ctx->user_intr_delay = 1;
}
ret = instance_execute_func(ctx, funcidx, ptype, rtype, param, result);
ret = exec_push_vals(ctx, ptype, param);
if (ret != 0) {
goto fail;
}
ret = instance_execute_func(ctx, funcidx, ptype, rtype);
do {
if (ret == ETOYWASMUSERINTERRUPT) {
struct timespec now;
Expand All @@ -898,6 +902,8 @@ exec_func(struct exec_context *ctx, uint32_t funcidx,
assert(ctx->trapped);
const struct trap_info *trap = &ctx->trap;
*trapp = trap;
} else if (ret == 0) {
exec_pop_vals(ctx, rtype, result);
}
fail:
return ret;
Expand Down
49 changes: 17 additions & 32 deletions lib/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,23 +1045,18 @@ int
exec_expr(uint32_t funcidx, const struct expr *expr,
const struct localtype *localtype,
const struct resulttype *parametertype, uint32_t nresults,
const struct cell *params, struct cell *results,
struct exec_context *ctx)
const struct cell *params, struct exec_context *ctx)
{
int ret;

assert(ctx->instance != NULL);
assert(ctx->instance->module != NULL);

ctx->nstackused_saved = ctx->stack.lsize;
ret = frame_enter(ctx, ctx->instance, funcidx, &expr->ei, localtype,
parametertype, nresults, params);
if (ret != 0) {
return ret;
}
ctx->p = expr->start;
ctx->results = results;
ctx->nresults = nresults;
return exec_expr_continue(ctx);
}

Expand Down Expand Up @@ -1169,12 +1164,6 @@ exec_expr_continue(struct exec_context *ctx)
return ret;
}
}
uint32_t nresults = ctx->nresults;
assert(ctx->stack.lsize == ctx->nstackused_saved + nresults);
cells_copy(ctx->results,
&VEC_ELEM(ctx->stack, ctx->stack.lsize - nresults),
nresults);
ctx->stack.lsize -= nresults;
return 0;
}

Expand Down Expand Up @@ -1274,10 +1263,8 @@ exec_const_expr(const struct expr *expr, enum valtype type, struct val *result,
};
int ret;
uint32_t csz = valtype_cellsize(type);
struct cell result_cells[4];
assert(ARRAYCOUNT(result_cells) >= csz);
ret = exec_expr(FUNCIDX_INVALID, expr, &no_locals, &empty, csz, NULL,
result_cells, ctx);
ctx);
/*
* it's very unlikely for a const expr to use a restart.
* but just in case.
Expand All @@ -1290,8 +1277,19 @@ exec_const_expr(const struct expr *expr, enum valtype type, struct val *result,
if (ret != 0) {
return ret;
}
struct resulttype rt = {
.types = &type,
.ntypes = 1,
.is_static = true,
#if defined(TOYWASM_USE_RESULTTYPE_CELLIDX)
.cellidx =
{
NULL,
},
#endif
};
exec_pop_vals(ctx, &rt, result);
assert(ctx->frames.lsize == saved_height);
val_from_cells(result, result_cells, csz);
return 0;
}

Expand Down Expand Up @@ -1765,8 +1763,7 @@ retry:;
*/
int
invoke(struct funcinst *finst, const struct resulttype *paramtype,
const struct resulttype *resulttype, const struct cell *params,
struct cell *results, struct exec_context *ctx)
const struct resulttype *resulttype, struct exec_context *ctx)
{
const struct functype *ft = funcinst_functype(finst);

Expand All @@ -1781,28 +1778,16 @@ invoke(struct funcinst *finst, const struct resulttype *paramtype,
}
}

uint32_t nresults = resulttype_cellsize(&ft->result);
int ret;
/* Sanity check */
assert(ctx->stack.lsize >= resulttype_cellsize(&ft->parameter));

/*
* Set up the context as if it was a restart of a "call" instruction.
*/
uint32_t nparams = resulttype_cellsize(&ft->parameter);
ret = stack_prealloc(ctx, nparams);
if (ret != 0) {
return ret;
}
struct cell *locals = &VEC_NEXTELEM(ctx->stack);
cells_copy(locals, params, nparams);
ctx->nstackused_saved = ctx->stack.lsize;
ctx->stack.lsize += nparams;

ctx->event_u.call.func = finst;
ctx->event = EXEC_EVENT_CALL;

ctx->nresults = nresults;
ctx->results = results;

/*
* and then "restart" the context execution.
*/
Expand Down
11 changes: 2 additions & 9 deletions lib/exec.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,12 @@ struct val;
int exec_expr(uint32_t funcidx, const struct expr *expr,
const struct localtype *localtype,
const struct resulttype *parametertype, uint32_t nresults,
const struct cell *params, struct cell *results,
struct exec_context *ctx);
const struct cell *params, struct exec_context *ctx);
int exec_expr_continue(struct exec_context *ctx);

int exec_const_expr(const struct expr *expr, enum valtype type,
struct val *result, struct exec_context *ctx);

int exec_push_vals(struct exec_context *ctx, const struct resulttype *rt,
const struct val *params);
void exec_pop_vals(struct exec_context *ctx, const struct resulttype *rt,
struct val *results);

int memory_init(struct exec_context *ctx, uint32_t memidx, uint32_t dataidx,
uint32_t d, uint32_t s, uint32_t n);
uint32_t memory_grow(struct exec_context *ctx, uint32_t memidx, uint32_t sz);
Expand All @@ -52,8 +46,7 @@ int fetch_exec_next_insn(const uint8_t *p, struct cell *stack,
void rewind_stack(struct exec_context *ctx, uint32_t height, uint32_t arity);

int invoke(struct funcinst *finst, const struct resulttype *paramtype,
const struct resulttype *resulttype, const struct cell *params,
struct cell *results, struct exec_context *ctx);
const struct resulttype *resulttype, struct exec_context *ctx);

int check_interrupt(struct exec_context *ctx);
int check_interrupt_interval_ms(struct exec_context *ctx);
Expand Down
13 changes: 7 additions & 6 deletions lib/exec_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "report.h"
#include "vec.h"

struct val;

struct label {
uint32_t pc;
uint32_t height; /* saved height of operand stack */
Expand Down Expand Up @@ -245,12 +247,6 @@ struct exec_context {
} timer;
} restart_u;

/* To simplify restart api */
struct cell *results;
const struct resulttype *resulttype;
struct val *results_val;
uint32_t nresults;
uint32_t nstackused_saved;
#if defined(TOYWASM_USE_USER_SCHED)
int exec_ret;
void (*exec_done)(struct exec_context *);
Expand All @@ -273,3 +269,8 @@ struct exec_context {
void exec_context_init(struct exec_context *ctx, struct instance *inst);
void exec_context_clear(struct exec_context *ctx);
void exec_context_print_stats(struct exec_context *ctx);

int exec_push_vals(struct exec_context *ctx, const struct resulttype *rt,
const struct val *params);
void exec_pop_vals(struct exec_context *ctx, const struct resulttype *rt,
struct val *results);
73 changes: 6 additions & 67 deletions lib/instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ instance_create_execute_init(struct instance *inst, struct exec_context *ctx)
if (m->has_start) {
assert(m->start < m->nimportedfuncs + m->nfuncs);
struct funcinst *finst = VEC_ELEM(inst->funcs, m->start);
ret = invoke(finst, NULL, NULL, NULL, NULL, ctx);
ret = invoke(finst, NULL, NULL, ctx);
while (IS_RESTARTABLE(ret)) {
xlog_trace("%s: restarting execution of the start "
"function\n",
Expand Down Expand Up @@ -553,87 +553,26 @@ instance_destroy(struct instance *inst)
int
instance_execute_func(struct exec_context *ctx, uint32_t funcidx,
const struct resulttype *paramtype,
const struct resulttype *resulttype,
const struct val *params, struct val *results)
const struct resulttype *resulttype)
{
struct funcinst *finst = VEC_ELEM(ctx->instance->funcs, funcidx);
uint32_t param_ncells = resulttype_cellsize(paramtype);
uint32_t result_ncells = resulttype_cellsize(resulttype);
struct cell *param_cells = NULL;
struct cell *result_cells = NULL;
int ret;
if (param_ncells > 0) {
param_cells = calloc(param_ncells, sizeof(*param_cells));
if (param_cells == NULL) {
ret = ENOMEM;
goto fail;
}
}
if (result_ncells > 0) {
result_cells = calloc(result_ncells, sizeof(*result_cells));
if (result_cells == NULL) {
ret = ENOMEM;
goto fail;
}
}
vals_to_cells(params, param_cells, paramtype);
ret = invoke(finst, paramtype, resulttype, param_cells, result_cells,
ctx);
if (ret == 0) {
vals_from_cells(results, result_cells, resulttype);
} else if (IS_RESTARTABLE(ret)) {
/*
* ctx->nresults is set by invoke().
* while it's redundant, it can be used by
* instance_exec_continue() to save
* a resulttype_cellsize() call.
*/
assert(ctx->nresults == result_ncells);
ctx->resulttype = resulttype; /* for possible restart */
ctx->results_val = results;
}
fail:
free(param_cells);
free(result_cells);
return ret;
return invoke(finst, paramtype, resulttype, ctx);
}

int
instance_execute_continue(struct exec_context *ctx)
{
const struct resulttype *resulttype = ctx->resulttype;
struct cell *result_cells = NULL;
uint32_t result_ncells = ctx->nresults;
int ret;

assert(result_ncells == resulttype_cellsize(resulttype));
if (result_ncells > 0) {
result_cells = calloc(result_ncells, sizeof(*result_cells));
if (result_cells == NULL) {
ret = ENOMEM;
goto fail;
}
}
ctx->results = result_cells;
ret = exec_expr_continue(ctx);
if (ret == 0 && result_ncells > 0) {
vals_from_cells(ctx->results_val, result_cells, resulttype);
}
fail:
free(result_cells);
return ret;
return exec_expr_continue(ctx);
}

int
instance_execute_func_nocheck(struct exec_context *ctx, uint32_t funcidx,
const struct val *params, struct val *results)
instance_execute_func_nocheck(struct exec_context *ctx, uint32_t funcidx)
{
const struct module *m = ctx->instance->module;
const struct functype *ft = module_functype(m, funcidx);
const struct resulttype *ptype = &ft->parameter;
const struct resulttype *rtype = &ft->result;
return instance_execute_func(ctx, funcidx, ptype, rtype, params,
results);
return instance_execute_func(ctx, funcidx, ptype, rtype);
}

int
Expand Down
7 changes: 2 additions & 5 deletions lib/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,13 @@ void instance_destroy(struct instance *inst);
*/
int instance_execute_func(struct exec_context *ctx, uint32_t funcidx,
const struct resulttype *paramtype,
const struct resulttype *resulttype,
const struct val *params, struct val *results);
const struct resulttype *resulttype);

/*
* instance_execute_func_nocheck is meant to be used where the caller
* already knows the function type for sure.
*/
int instance_execute_func_nocheck(struct exec_context *ctx, uint32_t funcidx,
const struct val *params,
struct val *results);
int instance_execute_func_nocheck(struct exec_context *ctx, uint32_t funcidx);

/*
* instance_execute_continue:
Expand Down
11 changes: 9 additions & 2 deletions libwasi/wasi_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,15 @@ exec_thread_start_func(struct exec_context *ctx, const struct thread_arg *arg)
* Note: the type of this function has already been confirmed by
* wasi_threads_instance_set_thread_spawn_args.
*/
return instance_execute_func_nocheck(ctx, wasi->thread_start_funcidx,
param, NULL);
const uint32_t funcidx = wasi->thread_start_funcidx;
const struct functype *ft =
module_functype(ctx->instance->module, funcidx);
const struct resulttype *rt = &ft->parameter;
int ret = exec_push_vals(ctx, rt, param);
if (ret != 0) {
return ret;
}
return instance_execute_func_nocheck(ctx, funcidx);
}

static void
Expand Down

0 comments on commit 4afd257

Please sign in to comment.