protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit cc85b900aa6e0317b4332bccf945761e19955bc9
parent aae7d899797b594d46110bf644c40c98824295ac
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 16 Jul 2021 15:36:55 -0700

resolver offsets

This allows us to keep track of resolver stacks for each callframe

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/cursor.h | 20++++++++++++++++++++
Msrc/wasm.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/wasm.h | 2++
3 files changed, 84 insertions(+), 35 deletions(-)

diff --git a/src/cursor.h b/src/cursor.h @@ -159,6 +159,26 @@ static inline int pull_data_into_cursor(struct cursor *cursor, return 1; } + +static inline unsigned char *cursor_top(struct cursor *cur, int len) +{ + if (unlikely(cur->p - len < cur->start)) { + printf("cursor_top oob\n"); + return NULL; + } + return cur->p - len; +} + +static inline int cursor_top_int(struct cursor *cur, int *i) +{ + u8 *p; + if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) { + return 0; + } + *i = *((int*)p); + return 1; +} + static inline int cursor_pop(struct cursor *cur, u8 *data, int len) { if (unlikely(cur->p - len < cur->start)) { diff --git a/src/wasm.c b/src/wasm.c @@ -43,37 +43,20 @@ struct expr_parser { static INLINE struct callframe *top_callframe(struct cursor *cur) { - if (unlikely(cur->p <= cur->start)) { - return NULL; - } - return ((struct callframe*)cur->p) - 1; + return (struct callframe*)cursor_top(cur, sizeof(struct callframe)); } static INLINE struct cursor *interp_codeptr(struct wasm_interp *interp) { struct callframe *frame; - frame = top_callframe(&interp->callframes); - if (unlikely(!frame)) + if (unlikely(!(frame = top_callframe(&interp->callframes)))) return 0; return &frame->code; } -static INLINE int cursor_popdata(struct cursor *cur, unsigned char *dest, int len) -{ - if (unlikely(cur->p - len < cur->start)) - return 0; - - cur->p -= len; - - if (dest) - memcpy(dest, cur->p, len); - - return 1; -} - static INLINE int cursor_popval(struct cursor *cur, struct val *val) { - return cursor_popdata(cur, (unsigned char*)val, sizeof(*val)); + return cursor_pop(cur, (unsigned char*)val, sizeof(*val)); } static const char *valtype_name(enum valtype valtype) @@ -364,12 +347,12 @@ static INLINE int cursor_push_callframe(struct cursor *cur, struct callframe *fr static INLINE int cursor_pop_callframe(struct cursor *cur, struct callframe *frame) { - return cursor_popdata(cur, (unsigned char*)frame, sizeof(*frame)); + return cursor_pop(cur, (u8*)frame, sizeof(*frame)); } static INLINE int cursor_popint(struct cursor *cur, int *i) { - return cursor_popdata(cur, (unsigned char *)i, sizeof(int)); + return cursor_pop(cur, (u8 *)i, sizeof(int)); } @@ -2239,6 +2222,27 @@ static INLINE int call_func(struct wasm_interp *interp, struct func *func, int f return interp_error(interp, "corrupt func type: %02x", func->type); } +static inline int count_resolvers(struct wasm_interp *interp) +{ + return cursor_count(&interp->resolver_stack, sizeof(struct resolver)); +} + +static inline int count_local_resolvers(struct wasm_interp *interp, int *count) +{ + int offset; + u8 *p; + if (unlikely(!cursor_top_int(&interp->resolver_offsets, &offset))) { + return interp_error(interp, "no top resolver offset?"); + } + p = interp->resolver_stack.start + offset * sizeof(struct resolver); + if (unlikely(p < interp->resolver_stack.start || + p >= interp->resolver_stack.end)) { + return interp_error(interp, "resolver offset oob?"); + } + *count = (interp->resolver_stack.p - p) / sizeof(struct resolver); + return 1; +} + static int prepare_call(struct wasm_interp *interp, int func_index) { static u8 tmp[0xFF]; @@ -2265,6 +2269,11 @@ static int prepare_call(struct wasm_interp *interp, int func_index) if (unlikely(!cursor_push_int(&interp->locals_offsets, offset))) return interp_error(interp, "push locals offset"); + offset = count_resolvers(interp); + /* this is like locals offsets but for label resolvers */ + if (unlikely(!cursor_push_int(&interp->resolver_offsets, offset))) + return interp_error(interp, "push resolver offset"); + /* get type signature to know how many locals to push as params */ if (unlikely(!(functype = get_function_type(interp, func_index)))) { return interp_error(interp, @@ -2338,7 +2347,6 @@ static int interp_call(struct wasm_interp *interp) return 0; } - /* call the function! */ if (unlikely(!interp_code(interp))) { return interp_error(interp, "call %s", get_function_name_for_error(interp, func_index)); @@ -2422,9 +2430,9 @@ static INLINE int pop_resolver(struct wasm_interp *interp, struct resolver *reso if (!cursor_pop(&interp->resolver_stack, (u8*)resolver, sizeof(*resolver))) { return interp_error(interp, "pop resolver"); } - debug("popped resolver stack %d i_%s %ld\n", + debug("popped resolver stack %d i_%s %d\n", resolver->label, instr_name(resolver->end_tag), - cursor_count(&interp->resolver_stack, sizeof(*resolver))); + count_resolvers(interp)); return 1; } @@ -3018,7 +3026,7 @@ static int interp_instr(struct wasm_interp *interp, u8 tag) int interp_code(struct wasm_interp *interp) { unsigned char tag; - int offset; + int offset, num_resolvers = 0; struct cursor *code; for (;;) { @@ -3027,14 +3035,28 @@ int interp_code(struct wasm_interp *interp) } if (unlikely(!pull_byte(code, &tag))) { - //cursor_print_around(code, 10); - return interp_error(interp, "instr tag"); - } - - if (unlikely(tag == i_end)) { - if (!cursor_popint(&interp->locals_offsets, &offset)) - return interp_error(interp, "pop locals_offset"); - break; + return interp_error(interp, "no more instrs to pull"); + } + + if (tag == i_end) { + if (unlikely(!count_local_resolvers(interp, + &num_resolvers))) { + return interp_error(interp, + "count local resolvers"); + } + + if (num_resolvers == 0) { + if (!cursor_popint(&interp->resolver_offsets, + &offset)) { + return interp_error(interp, + "pop resolver_offsets"); + } + if (!cursor_popint(&interp->locals_offsets, + &offset)) + return interp_error(interp, + "pop locals_offset"); + break; + } } if (unlikely(!interp_instr(interp, tag))) { @@ -3100,11 +3122,12 @@ void wasm_interp_init(struct wasm_interp *interp, struct module *module) unsigned char *mem; int ok, fns, errors_size, stack_size, locals_size, offsets_size, callframes_size, resolver_size, labels_size, num_labels_size, - labels_capacity, num_labels_elemsize, memsize; + labels_capacity, num_labels_elemsize, memsize, resolver_offsets_size; memset(interp, 0, sizeof(*interp)); interp->module = module; interp->module->start_fn = -1; + interp->prev_resolvers = 0; //stack = calloc(1, STACK_SPACE); fns = functions_count(module); @@ -3118,6 +3141,7 @@ void wasm_interp_init(struct wasm_interp *interp, struct module *module) num_labels_size = fns * num_labels_elemsize; locals_size = sizeof(struct val) * 0xFF; offsets_size = sizeof(int) * 0xFF; + resolver_offsets_size = offsets_size; callframes_size = sizeof(struct callframe) * 0xFF; resolver_size = sizeof(struct resolver) * MAX_LABELS; @@ -3131,6 +3155,7 @@ void wasm_interp_init(struct wasm_interp *interp, struct module *module) num_labels_size + locals_size + offsets_size + + resolver_offsets_size + callframes_size + resolver_size; @@ -3145,6 +3170,7 @@ void wasm_interp_init(struct wasm_interp *interp, struct module *module) cursor_slice(&interp->mem, &interp->errors.cur, errors_size) && cursor_slice(&interp->mem, &interp->locals, locals_size) && cursor_slice(&interp->mem, &interp->locals_offsets, offsets_size) && + cursor_slice(&interp->mem, &interp->resolver_offsets, resolver_offsets_size) && cursor_slice(&interp->mem, &interp->callframes, callframes_size) && cursor_slice(&interp->mem, &interp->resolver_stack, resolver_size) && array_alloc(&interp->mem, &interp->labels, labels_capacity) && @@ -3177,6 +3203,7 @@ int interp_wasm_module(struct wasm_interp *interp) // reset cursors reset_cursor(&interp->stack); reset_cursor(&interp->resolver_stack); + reset_cursor(&interp->resolver_offsets); reset_cursor(&interp->errors.cur); reset_cursor(&interp->locals); reset_cursor(&interp->locals_offsets); diff --git a/src/wasm.h b/src/wasm.h @@ -472,6 +472,7 @@ struct resolver { struct wasm_interp { struct module *module; + int prev_resolvers; struct errors errors; /* struct error */ size_t ops; @@ -481,6 +482,7 @@ struct wasm_interp { struct cursor mem; /* u8/mixed */ struct cursor locals; /* struct val */ struct cursor locals_offsets; /* int */ + struct cursor resolver_offsets; /* int */ struct array labels; /* struct labels */ struct array num_labels;