Skip to content

Commit

Permalink
redo tail call for validation
Browse files Browse the repository at this point in the history
  • Loading branch information
yamt committed May 7, 2024
1 parent c9f51bf commit fa9a53d
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 57 deletions.
2 changes: 0 additions & 2 deletions lib/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,5 @@ const uint8_t *pc2ptr(const struct module *m, uint32_t pc) __purefunc;
int resulttype_alloc(uint32_t ntypes, const enum valtype *types,
struct resulttype **resultp);
void resulttype_free(struct resulttype *p);
int fetch_process_next_insn(const uint8_t **pp, const uint8_t *ep,
struct context *ctx);

__END_EXTERN_C
79 changes: 37 additions & 42 deletions lib/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,72 +33,67 @@ read_op(const uint8_t **pp, const uint8_t *ep,
goto fail;
}
inst = inst8;
while (true) {
const struct instruction_desc *desc;
if (inst >= table_size) {
const struct instruction_desc *desc;
if (__predict_false(inst >= table_size)) {
goto invalid_inst;
}
desc = &table[inst];
if (desc->next_table != NULL) {
table = desc->next_table;
table_size = desc->next_table_size;
group = desc->name;
/*
* Note: wasm "sub" opcodes are LEB128.
* cf. https://github.com/WebAssembly/spec/issues/1228
*/
ret = read_leb_u32(pp, ep, &inst);
if (__predict_false(ret != 0)) {
goto fail;
}
if (__predict_false(inst >= table_size)) {
goto invalid_inst;
}
desc = &table[inst];
if (desc->next_table != NULL) {
table = desc->next_table;
table_size = desc->next_table_size;
group = desc->name;
/*
* Note: wasm "sub" opcodes are LEB128.
* cf. https://github.com/WebAssembly/spec/issues/1228
*/
ret = read_leb_u32(pp, ep, &inst);
if (ret != 0) {
goto fail;
}
continue;
}
if (desc->name == NULL) {
}
if (__predict_false(desc->name == NULL)) {
invalid_inst:
xlog_error("unimplemented instruction %02" PRIx32
" in group '%s'",
inst, group);
ret = EINVAL;
goto fail;
}
*descp = desc;
break;
xlog_error("unimplemented instruction %02" PRIx32
" in group '%s'",
inst, group);
ret = EINVAL;
goto fail;
}
*descp = desc;
ret = 0;
fail:
return ret;
}

int
fetch_process_next_insn(const uint8_t **pp, const uint8_t *ep,
struct context *ctx)
fetch_validate_next_insn(const uint8_t *p, const uint8_t *ep,
struct validation_context *vctx)
{
xassert(ep != NULL);
const struct instruction_desc *desc;
struct validation_context *vctx = ctx->validation;
#if defined(TOYWASM_ENABLE_TRACING_INSN)
uint32_t pc;
if (vctx != NULL) {
pc = ptr2pc(vctx->module, *pp);
}
pc = ptr2pc(vctx->module, p);
#endif
int ret;

ret = read_op(pp, ep, &desc);
ret = read_op(&p, ep, &desc);
if (ret != 0) {
goto fail;
}
xlog_trace_insn("inst %06" PRIx32 " %s", pc, desc->name);
#if defined(TOYWASM_ENABLE_TRACING_INSN)
// uint32_t orig_n = vctx->valtypes.lsize;
#endif
if (vctx->const_expr && (desc->flags & INSN_FLAG_CONST) == 0) {
ret = validation_failure(vctx,
"instruction \"%s\" not "
"allowed in a const expr",
desc->name);
goto fail;
}
__musttail return desc->process(pp, ep, ctx);
__musttail return desc->validate(p, ep, vctx);
fail:
return ret;
}
Expand All @@ -110,6 +105,7 @@ read_expr_common(const uint8_t **pp, const uint8_t *ep, struct expr *expr,
struct resulttype *result_types, bool const_expr,
struct load_context *lctx)
{
xassert(ep != NULL);
const uint8_t *p = *pp;
int ret;

Expand Down Expand Up @@ -162,15 +158,14 @@ read_expr_common(const uint8_t **pp, const uint8_t *ep, struct expr *expr,
goto fail;
}

struct context ctx0;
struct context *ctx = &ctx0;
ctx->validation = vctx;
ctx->exec = NULL;
while (true) {
ret = fetch_process_next_insn(&p, ep, ctx);
ret = fetch_validate_next_insn(p, ep, vctx);
if (ret != 0) {
goto fail;
}
assert(vctx->p > p);
p = vctx->p;
assert(p <= ep);
if (vctx->cframes.lsize == 0) {
break;
}
Expand Down
47 changes: 36 additions & 11 deletions lib/insn.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,9 @@ schedule_exception(struct exec_context *ectx)
#define SAVE_STACK_PTR
#define LOAD_STACK_PTR
#define ORIG_PC (*pp)
#define INSN_SUCCESS __musttail return fetch_process_next_insn(pp, ep, ctx)
#define INSN_SUCCESS_RETURN return 0
#define INSN_SUCCESS return 0
#define INSN_SUCCESS_RETURN INSN_SUCCESS
#define INSN_SUCCESS_BLOCK_END INSN_SUCCESS
#if defined(TOYWASM_USE_SEPARATE_EXECUTE)
#define PREPARE_FOR_POSSIBLE_RESTART
#define INSN_FAIL_RESTARTABLE(NAME) INSN_FAIL
Expand Down Expand Up @@ -599,6 +600,7 @@ schedule_exception(struct exec_context *ectx)
#undef PREPARE_FOR_POSSIBLE_RESTART
#undef INSN_SUCCESS
#undef INSN_SUCCESS_RETURN
#undef INSN_SUCCESS_BLOCK_END
#undef INSN_FAIL
#undef INSN_FAIL_RESTARTABLE
#undef STACK
Expand Down Expand Up @@ -628,6 +630,7 @@ schedule_exception(struct exec_context *ectx)
SAVE_STACK_PTR; \
ctx->p = p; \
return 0
#define INSN_SUCCESS_BLOCK_END assert(false)
#define PREPARE_FOR_POSSIBLE_RESTART struct cell *saved_stack_ptr = stack
#define INSN_FAIL_RESTARTABLE(NAME) \
assert(ret != 0); \
Expand Down Expand Up @@ -678,6 +681,7 @@ schedule_exception(struct exec_context *ectx)
#undef PREPARE_FOR_POSSIBLE_RESTART
#undef INSN_SUCCESS
#undef INSN_SUCCESS_RETURN
#undef INSN_SUCCESS_BLOCK_END
#undef INSN_FAIL
#undef INSN_FAIL_RESTARTABLE
#undef ep
Expand All @@ -691,16 +695,19 @@ schedule_exception(struct exec_context *ectx)
#define VALIDATING true
#define VCTX ctx
#define INSN_IMPL(NAME) \
int validate_##NAME(const uint8_t **pp, const uint8_t *ep, \
struct validation_context *ctx)
#define LOAD_PC const uint8_t *p __attribute__((__unused__)) = *pp
#define SAVE_PC *pp = p
int validate_##NAME(const uint8_t *p, const uint8_t *ep, \
struct validation_context *ctx)
#define LOAD_PC const uint8_t *p0 __attribute__((__unused__)) = p
#define SAVE_PC
#define RELOAD_PC
#define SAVE_STACK_PTR
#define LOAD_STACK_PTR
#define ORIG_PC (*pp)
#define INSN_SUCCESS return 0
#define ORIG_PC p0
#define INSN_SUCCESS __musttail return fetch_validate_next_insn(p, ep, ctx)
#define INSN_SUCCESS_RETURN INSN_SUCCESS
#define INSN_SUCCESS_BLOCK_END \
vctx->p = p; \
return 0
#define PREPARE_FOR_POSSIBLE_RESTART
#define INSN_FAIL_RESTARTABLE(NAME) INSN_FAIL
#define INSN_FAIL \
Expand All @@ -709,10 +716,16 @@ schedule_exception(struct exec_context *ectx)
return ret
#undef push_val
#undef pop_val
#define push_val(v, csz, ctx) do {} while (0)
#define pop_val(v, csz, ctx) do {} while (0)
#define push_val(v, csz, ctx) \
do { \
} while (0)
#define pop_val(v, csz, ctx) \
do { \
} while (0)
#define STACK NULL
#define STACK_ADJ(n) do {} while(0)
#define STACK_ADJ(n) \
do { \
} while (0)

#include "insn_impl.h"

Expand All @@ -730,6 +743,7 @@ schedule_exception(struct exec_context *ectx)
#undef PREPARE_FOR_POSSIBLE_RESTART
#undef INSN_SUCCESS
#undef INSN_SUCCESS_RETURN
#undef INSN_SUCCESS_BLOCK_END
#undef INSN_FAIL
#undef INSN_FAIL_RESTARTABLE
#undef ep
Expand Down Expand Up @@ -864,13 +878,24 @@ fetch_exec_next_insn_fe(const uint8_t *p, struct cell *stack,

#endif /* defined(TOYWASM_USE_SEPARATE_EXECUTE) */

#if defined(TOYWASM_USE_SEPARATE_VALIDATE)
#define INSTRUCTION(b, n, f, FLAGS) \
[b] = { \
.name = n, \
.process = process_##f, \
.validate = validate_##f, \
.flags = FLAGS, \
.next_table = NULL, \
},
#else
#define INSTRUCTION(b, n, f, FLAGS) \
[b] = { \
.name = n, \
.process = process_##f, \
.flags = FLAGS, \
.next_table = NULL, \
},
#endif

#define INSTRUCTION_INDIRECT(b, n) \
[b] = { \
Expand Down
5 changes: 5 additions & 0 deletions lib/insn.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

struct context;
struct exec_context;
struct validation_context;
struct cell;

struct exec_instruction_desc {
Expand All @@ -22,6 +23,10 @@ struct instruction_desc {
const char *name;
int (*process)(const uint8_t **pp, const uint8_t *ep,
struct context *ctx);
#if defined(TOYWASM_USE_SEPARATE_VALIDATE)
int (*validate)(const uint8_t *p, const uint8_t *ep,
struct validation_context *vctx);
#endif
const struct instruction_desc *next_table;
unsigned int next_table_size;
unsigned int flags;
Expand Down
4 changes: 2 additions & 2 deletions lib/insn_impl_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ INSN_IMPL(unreachable)
} else if (VALIDATING) {
mark_unreachable(VCTX);
}
return 0;
INSN_SUCCESS;
}

INSN_IMPL(nop) { INSN_SUCCESS; }
Expand Down Expand Up @@ -228,7 +228,7 @@ INSN_IMPL(end)
return ret;
}
}
INSN_SUCCESS_RETURN;
INSN_SUCCESS_BLOCK_END;
}
INSN_SUCCESS;
}
Expand Down
6 changes: 6 additions & 0 deletions lib/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ struct validation_context {
struct bitmap *refs;

const struct load_options *options;

#if defined(TOYWASM_USE_SEPARATE_VALIDATE)
const uint8_t *p;
#endif
};

/* validation */
Expand Down Expand Up @@ -85,3 +89,5 @@ int target_label_types(struct validation_context *ctx, uint32_t labelidx,

int record_type_annotation(struct validation_context *vctx, const uint8_t *p,
enum valtype t);
int fetch_validate_next_insn(const uint8_t *p, const uint8_t *ep,
struct validation_context *vctx);

0 comments on commit fa9a53d

Please sign in to comment.