commit ac22c121184c6ad6329ce449e1bcdc6c44138622
parent 6d5354ef9d578eea5005d93eceda11f967a5ee52
Author: William Casarin <jb55@jb55.com>
Date: Wed, 14 Jul 2021 09:13:44 -0700
setup interpreter to be run many times
Diffstat:
4 files changed, 96 insertions(+), 65 deletions(-)
diff --git a/src/bench.c b/src/bench.c
@@ -20,13 +20,12 @@ static int bench_wasm(unsigned char *wasm, unsigned long len, int times)
return 0;
}
- wasm_interp_init(&interp);
+ wasm_interp_init(&interp, &p.module);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
for (i = 0; i < times; i++) {
- if (!interp_wasm_module(&interp, &p.module)) {
- printf("bench: interp_wasm_module failed\n");
- break;
+ if (!interp_wasm_module(&interp)) {
+ //print_error_backtrace(&interp.errors);
}
ops += interp.ops;
}
@@ -35,7 +34,7 @@ static int bench_wasm(unsigned char *wasm, unsigned long len, int times)
nanos = (t2.tv_sec - t1.tv_sec) * (long)1e9 + (t2.tv_nsec - t1.tv_nsec);
ms = nanos / 1e6;
printf("ns/run\t%ld\nms/run\t%f\nns\t%ld\nms\t%ld\nops\t%d\nns/op\t%ld\n",
- nanos/times, (double)ms/(double)times, nanos, ms, ops, nanos/ops);
+ nanos/times, (double)ms/(double)times, nanos, ms, ops, nanos/(ops+1));
wasm_interp_free(&interp);
wasm_parser_free(&p);
diff --git a/src/cursor.h b/src/cursor.h
@@ -6,6 +6,7 @@
#include "varint.h"
#include <stdio.h>
+#include <assert.h>
#include <string.h>
#define unlikely(x) __builtin_expect((x),0)
@@ -21,6 +22,11 @@ struct array {
unsigned int elem_size;
};
+static inline void reset_cursor(struct cursor *cursor)
+{
+ cursor->p = cursor->start;
+}
+
static inline void make_cursor(u8 *start, u8 *end, struct cursor *cursor)
{
cursor->start = start;
diff --git a/src/wasm.c b/src/wasm.c
@@ -295,7 +295,7 @@ static inline int offset_stack_top(struct cursor *cur)
return *(p - sizeof(*p));
}
-static void print_error_backtrace(struct cursor *errors)
+void print_error_backtrace(struct cursor *errors)
{
struct cursor errs;
struct error err;
@@ -1872,7 +1872,7 @@ static inline int interp_i32_gt_u(struct wasm_interp *interp)
return 0;
}
- c.i32 = (unsigned int)b.i32 > (unsigned int)a.i32;
+ c.i32 = (unsigned int)b.i32 > (unsigned int)a.i32;
return cursor_pushval(&interp->stack, &c);
}
@@ -2118,8 +2118,11 @@ static int resolve_label(struct wasm_interp *interp)
label = index_label(&interp->labels, frame->fn, label_ind);
assert(label);
- assert(!label_is_resolved(label));
+ if (label_is_resolved(label)) {
+ debug("label %d is already resolved\n", label_ind);
+ return 1;
+ }
label->jump = frame->code.p - frame->code.start;
label->instr_pos |= 0x80000000;
@@ -2209,9 +2212,6 @@ static int upsert_label(struct wasm_interp *interp, int fn,
num_labels = func_num_labels(interp, fn);
- debug("upsert_label: %d labels for %s\n",
- *num_labels, get_function_name(interp->module, fn));
-
if (*num_labels > 0 && ((*ind = find_label(interp, fn, instr_pos)) == 0)) {
// we already have the label
return 1;
@@ -2223,6 +2223,9 @@ static int upsert_label(struct wasm_interp *interp, int fn,
return 0;
}
+ debug("upsert_label: %d labels for %s\n",
+ *num_labels, get_function_name(interp->module, fn));
+
*ind = *num_labels;
label = index_label(&interp->labels, fn, *ind);
assert(label);
@@ -2234,7 +2237,7 @@ static int upsert_label(struct wasm_interp *interp, int fn,
}
-static int label_checkpoint(struct wasm_interp *interp)
+static int label_checkpoint(struct wasm_interp *interp, int *jumped)
{
u32 instr_pos;
int ind;
@@ -2243,6 +2246,8 @@ static int label_checkpoint(struct wasm_interp *interp)
struct label *label;
struct callframe *frame;
+ *jumped = 0;
+
fns = functions_count(interp->module);
frame = top_callframe(&interp->callframes);
@@ -2267,10 +2272,13 @@ static int label_checkpoint(struct wasm_interp *interp)
if (label_is_resolved(label)) {
frame->code.p = frame->code.start + label->jump;
+ debug("label is resolved, jumping to %04lX\n",
+ frame->code.p - frame->code.start);
if (frame->code.p >= frame->code.end) {
interp_error(interp, "code pointer at or past end, evil jump?");
return 0;
}
+ *jumped = 1;
return 1;
}
@@ -2287,8 +2295,7 @@ static int label_checkpoint(struct wasm_interp *interp)
static int parse_block(struct wasm_interp *interp, struct block *block, u8 end_tag)
{
struct cursor *code;
-
- debug("parsing block");
+ int jumped;
if (!(code = interp_codeptr(interp))) {
interp_error(interp, "codeptr");
@@ -2300,7 +2307,7 @@ static int parse_block(struct wasm_interp *interp, struct block *block, u8 end_t
return 0;
}
- if (!label_checkpoint(interp)) {
+ if (!label_checkpoint(interp, &jumped)) {
interp_error(interp, "checkpoint");
return 0;
}
@@ -2323,7 +2330,7 @@ static inline int parse_memarg(struct cursor *code, struct memarg *memarg)
static int parse_instr(struct wasm_interp *interp, u8 tag, struct instr *op)
{
struct cursor *code;
-
+
if (!(code = interp_codeptr(interp))) {
interp_error(interp, "codeptr");
return 0;
@@ -2483,12 +2490,17 @@ static int parse_instr(struct wasm_interp *interp, u8 tag, struct instr *op)
static int branch_jump(struct wasm_interp *interp, u8 end_tag)
{
struct cursor instrs;
+ int jumped;
- if (!label_checkpoint(interp)) {
+ if (!label_checkpoint(interp, &jumped)) {
interp_error(interp, "label checkpoint");
return 0;
}
+ if (jumped) {
+ return 1;
+ }
+
// consume instructions, use resolver stack to resolve jumps
if (!parse_instrs_until(interp, end_tag, &instrs)) {
interp_error(interp, "parse instrs");
@@ -2592,10 +2604,6 @@ int interp_code(struct wasm_interp *interp)
return 1;
}
-#define STACK_SPACE 5242880
-#define MEM_SPACE 5242880
-#define LOCALS_SPACE 5242880
-
static int find_function(struct module *module, const char *name)
{
struct wexport *export;
@@ -2638,19 +2646,57 @@ void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t a
cursor_slice(&p->mem, &p->errs, 0xFFFF);
}
-void wasm_interp_init(struct wasm_interp *interp)
+void wasm_interp_init(struct wasm_interp *interp, struct module *module)
{
- static unsigned char *stack, *mem;
+ 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;
- interp->ops = 0;
+ memset(interp, 0, sizeof(*interp));
+ interp->module = module;
+
+ //stack = calloc(1, STACK_SPACE);
+ fns = functions_count(module);
+ labels_capacity = fns * MAX_LABELS;
+ num_labels_elemsize = sizeof(u16);
+
+ errors_size = 0xFFFF;
+ stack_size = 0xFFFF;
+ labels_size = labels_capacity * sizeof(struct label);
+ num_labels_size = fns * num_labels_elemsize;
+ locals_size = sizeof(struct val) * NUM_LOCALS;
+ offsets_size = sizeof(int) * 255;
+ callframes_size = sizeof(struct callframe) * 255;
+ resolver_size = sizeof(u16) * MAX_LABELS;
+
+ interp->labels.elem_size = sizeof(struct label);
+ interp->num_labels.elem_size = num_labels_elemsize;
- stack = calloc(1, STACK_SPACE);
- mem = calloc(1, MEM_SPACE);
+ memsize =
+ errors_size +
+ stack_size +
+ labels_size +
+ num_labels_size +
+ locals_size +
+ offsets_size +
+ callframes_size +
+ resolver_size;
- make_cursor(stack, stack + STACK_SPACE, &interp->stack);
- make_cursor(mem, mem + MEM_SPACE, &interp->mem);
+ mem = calloc(1, memsize);
+ make_cursor(mem, mem + memsize, &interp->mem);
+
+ ok =
+ cursor_slice(&interp->mem, &interp->stack, stack_size) &&
+ cursor_slice(&interp->mem, &interp->errors, errors_size) &&
+ cursor_slice(&interp->mem, &interp->locals, locals_size) &&
+ cursor_slice(&interp->mem, &interp->locals_offsets, 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) &&
+ array_alloc(&interp->mem, &interp->num_labels, fns);
- cursor_slice(&interp->mem, &interp->errors, 0xFFFF);
+ assert(ok);
}
void wasm_parser_free(struct wasm_parser *parser)
@@ -2660,52 +2706,31 @@ void wasm_parser_free(struct wasm_parser *parser)
void wasm_interp_free(struct wasm_interp *interp)
{
- free(interp->stack.start);
free(interp->mem.start);
}
-static int alloc_labels(struct wasm_interp *interp, int fns)
+int interp_wasm_module(struct wasm_interp *interp)
{
- const int capacity = fns * MAX_LABELS;
-
- interp->labels.elem_size = sizeof(struct label);
- interp->num_labels.elem_size = sizeof(u16);
+ int ok, func;
- return array_alloc(&interp->mem, &interp->labels, capacity) &&
- array_alloc(&interp->mem, &interp->num_labels, fns);
-
-}
-
-int interp_wasm_module(struct wasm_interp *interp, struct module *module)
-{
- int ok, func, fns;
-
- interp->module = module;
interp->ops = 0;
- if (module->code_section.num_funcs == 0) {
+ if (interp->module->code_section.num_funcs == 0) {
interp_error(interp, "empty module");
return 0;
}
// reset cursors
- interp->stack.p = interp->stack.start;
- interp->errors.p = interp->errors.start;
- interp->mem.p = interp->mem.start;
+ reset_cursor(&interp->stack);
+ reset_cursor(&interp->errors);
+ reset_cursor(&interp->locals);
+ reset_cursor(&interp->locals_offsets);
+ reset_cursor(&interp->callframes);
+ // don't reset labels for perf!
- fns = functions_count(module);
-
- ok =
- cursor_slice(&interp->mem, &interp->locals,
- sizeof(struct val) * NUM_LOCALS) &&
- cursor_slice(&interp->mem, &interp->locals_offsets, sizeof(int) * 255) &&
- cursor_slice(&interp->mem, &interp->callframes, sizeof(struct callframe) * 255) &&
- cursor_slice(&interp->mem, &interp->resolver_stack, sizeof(u32) * MAX_LABELS) &&
- alloc_labels(interp, fns);
-
- assert(ok);
+ //interp->mem.p = interp->mem.start;
- func = find_start_function(module);
+ func = find_start_function(interp->module);
if (func == -1) {
interp_error(interp, "no start function found");
ok = 0;
@@ -2740,8 +2765,8 @@ int run_wasm(unsigned char *wasm, unsigned long len)
return 0;
}
- wasm_interp_init(&interp);
- ok = interp_wasm_module(&interp, &p.module);
+ wasm_interp_init(&interp, &p.module);
+ ok = interp_wasm_module(&interp);
print_error_backtrace(&interp.errors);
printf("ops: %ld\nstack:\n", interp.ops);
print_stack(&interp.stack);
diff --git a/src/wasm.h b/src/wasm.h
@@ -446,10 +446,11 @@ struct wasm_parser {
int run_wasm(unsigned char *wasm, unsigned long len);
int parse_wasm(struct wasm_parser *p);
-void wasm_interp_init(struct wasm_interp *interp);
+void wasm_interp_init(struct wasm_interp *interp, struct module *module);
void wasm_parser_free(struct wasm_parser *parser);
void wasm_parser_init(struct wasm_parser *parser, u8 *wasm, size_t wasm_len, size_t arena_size);
void wasm_interp_free(struct wasm_interp *interp);
-int interp_wasm_module(struct wasm_interp *interp, struct module *module);
+int interp_wasm_module(struct wasm_interp *interp);
+void print_error_backtrace(struct cursor *errors);
#endif /* PROTOVERSE_WASM_H */