diff --git a/tcg/tcg.c b/tcg/tcg.c index 423ba72451..665b4ed0b7 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -6684,17 +6684,12 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) } *(uint32_t *)wasm_blob_ptr_base = s->code_ptr - wasm_blob_ptr_base - 4; - { - static __thread int dumped_store, dumped_load; + if (wasm_dump_pc_hi && pc_start >= wasm_dump_pc_lo && pc_start < wasm_dump_pc_hi) { uint32_t mod_len = *(uint32_t *)wasm_blob_ptr_base; const uint8_t *mod = wasm_blob_ptr_base + 4; - if (wasm_tb_had_store && !dumped_store) { - dumped_store = 1; - wasm_dump_module(mod, mod_len, "store"); - } else if (wasm_tb_had_load && !wasm_tb_had_store && !dumped_load) { - dumped_load = 1; - wasm_dump_module(mod, mod_len, "load"); - } + char dump_name[32]; + snprintf(dump_name, sizeof(dump_name), "pc-%08llx", (unsigned long long)pc_start); + wasm_dump_module(mod, mod_len, dump_name); } size_base = (uint32_t*)s->code_ptr; diff --git a/tcg/wasm32.c b/tcg/wasm32.c index 3e78b3b05e..5954c309ba 100644 --- a/tcg/wasm32.c +++ b/tcg/wasm32.c @@ -45,14 +45,19 @@ EMSCRIPTEN_KEEPALIVE int wasm_instantiated_tb_count(void) } EM_JS(void, wasm_dump_module_js, (int ptr, int len, int name), { + const bytes = Uint8Array.from(HEAP8.subarray(ptr, ptr + len)); + const dumpName = UTF8ToString(name); try { const fs = require('fs'); - const bytes = Uint8Array.from(HEAP8.subarray(ptr, ptr + len)); - const fname = '/tmp/tbdump-' + UTF8ToString(name) + '.wasm'; + const fname = '/tmp/tbdump-' + dumpName + '.wasm'; fs.writeFileSync(fname, bytes); out('WASM_DUMP wrote ' + fname + ' (' + len + ' bytes)'); } catch (e) { - /* Browser has no require('fs'); dump is a node-only analysis aid. */ + let hex = ''; + for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, '0'); + out('WASM_DUMP_HEX_BEGIN ' + dumpName + ' ' + len); + for (let i = 0; i < hex.length; i += 2048) out('WASM_DUMP_HEX ' + dumpName + ' ' + hex.slice(i, i + 2048)); + out('WASM_DUMP_HEX_END ' + dumpName); } }); @@ -1365,8 +1370,11 @@ static __thread uint8_t *diff_fulltlb_c[NB_MMU_MODES]; int wasm_diff_mode; int wasm_stateflush_enabled; int wasm_tlb_guard_enabled; +uint64_t wasm_dump_pc_lo; +uint64_t wasm_dump_pc_hi; int wasm_store_tci_disabled; int wasm_store_tci_hash; +int wasm_store_helper_tci; int wasm_store_bisect_on; int wasm_store_bisect_width; uint64_t wasm_store_pc_lo; @@ -1394,6 +1402,11 @@ EMSCRIPTEN_KEEPALIVE void wasm_set_store_tci_hash(int mode) wasm_store_tci_hash = mode; } +EMSCRIPTEN_KEEPALIVE void wasm_set_store_helper_tci(void) +{ + wasm_store_helper_tci = 1; +} + /* E15 bisection: compile a store TB only when (hash(pc) & mask) == val, else * TCI. Runtime-settable so the culprit set can be binary-searched with no * rebuild. */ @@ -1433,6 +1446,12 @@ EMSCRIPTEN_KEEPALIVE void wasm_tlb_guard_enable(void) wasm_tlb_guard_enabled = 1; } +EMSCRIPTEN_KEEPALIVE void wasm_set_dump_pc_window(uint32_t lo, uint32_t hi) +{ + wasm_dump_pc_lo = lo; + wasm_dump_pc_hi = hi; +} + int wasm_diff_on(void) { return wasm_diff_enabled; diff --git a/tcg/wasm32.h b/tcg/wasm32.h index c09765c1ef..0739de937a 100644 --- a/tcg/wasm32.h +++ b/tcg/wasm32.h @@ -58,16 +58,21 @@ extern __thread uint64_t wasm_cur_tb_pc; extern int wasm_diff_mode; extern int wasm_store_tci_disabled; extern int wasm_store_tci_hash; +extern int wasm_store_helper_tci; extern int wasm_store_bisect_on; extern int wasm_store_bisect_width; extern uint64_t wasm_store_pc_lo; extern uint64_t wasm_store_pc_hi; +extern uint64_t wasm_dump_pc_lo; +extern uint64_t wasm_dump_pc_hi; extern uint32_t wasm_store_bisect_mask; extern uint32_t wasm_store_bisect_val; void wasm_disable_store_tci(void); void wasm_set_store_tci_hash(int mode); +void wasm_set_store_helper_tci(void); void wasm_set_store_bisect(int width, uint32_t mask, uint32_t val); void wasm_set_store_pc_window(uint32_t lo, uint32_t hi); +void wasm_set_dump_pc_window(uint32_t lo, uint32_t hi); void wasm_diff_enable(void); void wasm_diff_enable2(void); int wasm_diff_on(void); diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc index 1edfdaf382..143b1ab0fc 100644 --- a/tcg/wasm32/tcg-target.c.inc +++ b/tcg/wasm32/tcg-target.c.inc @@ -3399,10 +3399,8 @@ static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bo wasm_tb_had_store = true; tcg_tci_out_qemu_ldst(s, opc, args); tcg_wasm_out_qemu_st(s, args, is_64); - /* ponytail: Store TBs Stay TCI - All-compiled stores still reproduce the 0x4201e210 panic. - * The narrower 32-bit-only fallback passed reader-open but hit an app-init watchdog in benchmark, - * so keep the upstream blanket fallback until the cross-width bug is fully fixed. */ - bool store_tci = !wasm_store_tci_disabled; + /* ponytail: Mixed Store TBs Stay TCI - Pure store TBs are safe, but a store+load/helper TB in uzlib corrupts the vCPU TLB arrays when compiled. */ + bool store_tci = !wasm_store_tci_disabled && (wasm_tb_had_load || wasm_tb_had_helper); if (s->gen_tb && (wasm_store_tci_hash || wasm_store_bisect_on)) { uint64_t pc = s->gen_tb->pc; uint32_t h = (uint32_t)((pc * 0x9e3779b97f4a7c15ull) >> 33); @@ -3427,6 +3425,9 @@ static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bo store_tci = ((h & 1) == (uint32_t)(wasm_store_tci_hash - 1)); } } + if (wasm_store_helper_tci && (wasm_tb_had_helper || wasm_tb_had_load)) { + store_tci = true; + } if (wasm_diff_mode != 2 && store_tci) { wasm_tci_only_tb = true; }