diff --git a/cli/repl.c b/cli/repl.c index 3496bada..d7d7a5c8 100644 --- a/cli/repl.c +++ b/cli/repl.c @@ -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; @@ -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; diff --git a/lib/exec.c b/lib/exec.c index 92f251b6..877a86c3 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -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); } @@ -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; } @@ -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. @@ -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; } @@ -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); @@ -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. */ diff --git a/lib/exec.h b/lib/exec.h index 9529a200..28519b62 100644 --- a/lib/exec.h +++ b/lib/exec.h @@ -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); @@ -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); diff --git a/lib/exec_context.h b/lib/exec_context.h index 7d6c9689..0cdae1a4 100644 --- a/lib/exec_context.h +++ b/lib/exec_context.h @@ -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 */ @@ -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 *); @@ -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); diff --git a/lib/instance.c b/lib/instance.c index e579fdc3..1a3a652d 100644 --- a/lib/instance.c +++ b/lib/instance.c @@ -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", @@ -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 diff --git a/lib/instance.h b/lib/instance.h index 17828c90..48f9f995 100644 --- a/lib/instance.h +++ b/lib/instance.h @@ -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: diff --git a/libwasi/wasi_threads.c b/libwasi/wasi_threads.c index 7457cf80..4f048f7a 100644 --- a/libwasi/wasi_threads.c +++ b/libwasi/wasi_threads.c @@ -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