From ae5f02b75767f4728344e7e802c2c5065684fba7 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Sat, 13 May 2023 08:45:11 +0900 Subject: [PATCH] remove unused jump table entries some modules have redundant blocks for some reasons. this commit removes jump table entries for them. --- lib/expr.c | 22 ++++++++++++++++++++++ lib/type.h | 6 ++++-- lib/validation.c | 9 ++++++++- lib/validation.h | 2 ++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/expr.c b/lib/expr.c index 9871f8f9..3e77f037 100644 --- a/lib/expr.c +++ b/lib/expr.c @@ -175,6 +175,28 @@ read_expr_common(const uint8_t **pp, const uint8_t *ep, struct expr *expr, i, j->pc, j->targetpc); } #endif + if (vctx->can_shrink_jump_table) { + assert(ei->jumps != NULL); + assert(ei->njumps > 0); + const struct jump *from = ei->jumps; + struct jump *to = ei->jumps; + const struct jump *ep = ei->jumps + ei->njumps; + while (from < ep) { + if (from->targetpc != JUMP_TABLE_INVALID_PC) { + *to++ = *from; + } + from++; + } + assert(to < from); + xlog_trace("jump table shrinked from %" PRIu32 " to %zu", + ei->njumps, to - ei->jumps); + ei->njumps = to - ei->jumps; + ret = resize_array((void **)&ei->jumps, sizeof(*ei->jumps), + ei->njumps); + if (ret != 0) { + xlog_error("ignoring jump table resize failure"); + } + } *pp = p; #if defined(TOYWASM_ENABLE_WRITER) expr->end = p; diff --git a/lib/type.h b/lib/type.h index cd71d07f..7feb60ef 100644 --- a/lib/type.h +++ b/lib/type.h @@ -17,9 +17,11 @@ #define WASM_PAGE_SIZE 65536 #define WASM_MAX_PAGES 65536 +#define JUMP_TABLE_INVALID_PC 0xffffffff + struct jump { - uint32_t pc; - uint32_t targetpc; + uint32_t pc; /* the address of block instruction (eg. block, loop) */ + uint32_t targetpc; /* the jump target addreass */ }; struct type_annotation { diff --git a/lib/validation.c b/lib/validation.c index 872113b8..b2524ce0 100644 --- a/lib/validation.c +++ b/lib/validation.c @@ -190,6 +190,7 @@ push_ctrlframe(uint32_t pc, enum ctrlframe_op op, uint32_t jumpslot, cframe->start_types = start_types; cframe->end_types = end_types; cframe->unreachable = false; + cframe->seen = false; cframe->height = ctx->valtypes.lsize; cframe->height_cell = ctx->ncells; assert(nsize == ctx->cframes.lsize); @@ -224,8 +225,12 @@ pop_ctrlframe(uint32_t pc, bool is_else, struct ctrlframe *cframep, assert(jump->targetpc == 0); if (cframe->op == FRAME_OP_LOOP) { jump->targetpc = jump->pc; - } else { + } else if (cframe->seen || (cframe->op == FRAME_OP_IF || + cframe->op == FRAME_OP_ELSE)) { jump->targetpc = pc; + } else { + ctx->can_shrink_jump_table = true; + jump->targetpc = JUMP_TABLE_INVALID_PC; } } ret = pop_valtypes(cframe->end_types, ctx); @@ -296,6 +301,7 @@ validation_context_reuse(struct validation_context *ctx) ctx->valtypes.lsize = 0; ctx->ncells = 0; ctx->locals.lsize = 0; + ctx->can_shrink_jump_table = false; } void @@ -324,6 +330,7 @@ target_label_types(struct validation_context *ctx, uint32_t labelidx, struct ctrlframe *cframe = &VEC_ELEM(ctx->cframes, ctx->cframes.lsize - labelidx - 1); const struct resulttype *rt = label_types(cframe); + cframe->seen = true; *rtp = rt; return 0; } diff --git a/lib/validation.h b/lib/validation.h index 7b8b7981..8c6aec55 100644 --- a/lib/validation.h +++ b/lib/validation.h @@ -11,6 +11,7 @@ struct ctrlframe { uint32_t height; uint32_t height_cell; bool unreachable; + bool seen; }; struct validation_context { @@ -28,6 +29,7 @@ struct validation_context { VEC(, enum valtype) locals; bool const_expr; + bool can_shrink_jump_table; bool has_datacount; uint32_t ndatas_in_datacount;