From ceccd4aa1ef0096841664a4eb757efbafdb0f383 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 16:27:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(mlirlitetest):=20=E6=AF=8F=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=8B=AC=E7=AB=8B=E5=AD=90=E6=B1=A0=20+=20=E4=B8=BB?= =?UTF-8?q?=E6=B1=A0=E8=B0=83=E5=A4=A7=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E5=99=A8=E6=8C=89=E5=87=BD=E6=95=B0=E5=88=86=E9=85=8D?= =?UTF-8?q?=E7=B4=AF=E7=A7=AF=E8=80=97=E5=B0=BD=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:跑到 Test 14 时 memhub 4MB 池耗尽 → "[MLIR-FAIL] MLIR 渲染: 常量/别名表分配失败"。 根因(按存活块账目反推):mlirlite 的 _MlirTablesInit 在**调用方池**里每次 FunctionPrint 重分配约 35–45KB 的常量表/别名表/scratch 且不释放;15 个测试共用一个 4MB 池 ⇒ 按函数泄漏跨测试累积,加上每节 64KB 输出缓冲与 32KB GV 缓冲,到第 14 个吃干。 改为"主池 + 子池":主池仅用于给每个测试切一块 SUB_POOL_SIZE(2MB) 子池(_sub_pool),测试内 IR 对象与渲染器 scratch 全部落在自己的子池,互不叠加;POOL_SIZE 4MB → 64MB(15 个子池,伙伴分配器按 2 的幂取块)。 --- MLIRLiteTest/App/main.vp | 64 +++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/MLIRLiteTest/App/main.vp b/MLIRLiteTest/App/main.vp index f4b740b..fdeaebb 100644 --- a/MLIRLiteTest/App/main.vp +++ b/MLIRLiteTest/App/main.vp @@ -10,8 +10,14 @@ import viperlib import mlirlite -# 内存大小(MLIR 渲染期会为每个函数分配 scratch/常量表,故给足 4MB) -POOL_SIZE: t.CDefine = 4194304 +# 主池大小:只用于给**每个测试切一块子池**(见 main / _sub_pool)。 +POOL_SIZE: t.CDefine = 67108864 +# 每个测试的子池大小。子池存在的意义:测试内的 IR 对象与 MLIR 渲染器每函数 +# **重分配**的 scratch/常量表/别名表(约 35–45KB/函数,见 mlirlite 的 +# _MlirTablesInit)都落在自己的子池里,互不叠加。若所有测试共用一个池,渲染器 +# 这套"按函数重分配、不释放"的开销会跨测试累积(此前 15 个测试共用 4MB, +# 到第 14 个把池吃干 → "MLIR 渲染: 常量/别名表分配失败")。 +SUB_POOL_SIZE: t.CDefine = 2097152 # 把 buf 中的 MLIR 文本落盘到 Test/MLIRLiteTest/output/,供 @@ -19,7 +25,7 @@ POOL_SIZE: t.CDefine = 4194304 # 目录必须已存在:fileio.File(MODE.W) 在目录缺失时静默失败(f.closed 保持 # True,StubMergerCollect.vp 有同类注释记录),故此处对 f.closed 显式告警, # 不静默吞掉失败。 -# path 缓冲取自 pool.alloc:缓冲随整个 pool 生命周期统一回收,故此处不调用 free +# path 缓冲取自 pool.alloc:缓冲随整个 pool 生命周期统一回收,故此处不调用 free # (pool 是 MemBuddy 伙伴分配器,支持 free,但本测试无需逐块回收)。 # dump 序号:name 传 None 时用于自动命名(auto_NN.mlir),便于在各测试点无参调用。 _DUMP_SEQ: int = 0 @@ -1445,10 +1451,28 @@ def test_extractvalue_multi_asm(pool: memhub.MemBuddy | t.CPtr): "extractvalue result not referenced") +def _sub_pool(main_pool: memhub.MemBuddy | t.CPtr) -> memhub.MemBuddy | t.CPtr: + """从主池切一块子池给单个测试用(伙伴分配器返回 2 的幂块,可直接作 arena) + + 每个测试在自己的子池里分配:测试内的 IR 对象与渲染器每函数重分配的 + scratch/常量表都落在子池,互不叠加(理由见 SUB_POOL_SIZE 注释)。子池不 + 单独回收——主池按"每个测试一块"给足,测试进程短命。 + """ + mem: rawptr = main_pool.alloc(SUB_POOL_SIZE) + if mem is None: + stdio.printf("FAIL: sub pool alloc failed (raise POOL_SIZE)\n") + stdlib.exit(1) + sub: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(mem, SUB_POOL_SIZE) + if sub is None: + stdio.printf("FAIL: sub pool MemBuddy init failed\n") + stdlib.exit(1) + return sub + + def main() -> int: testcheck.begin("MLIRLiteTest: mlirlite 库(MLIR llvm 方言文本生成)") - # 初始化 mpool + # 初始化主池:仅用于切子池(测试内分配一律走各自的子池) pool_mem: bytes = stdlib.malloc(POOL_SIZE) if pool_mem is None: stdio.printf("FAIL: malloc for pool failed\n") @@ -1458,21 +1482,21 @@ def main() -> int: stdio.printf("FAIL: memhub.MemBuddy init failed\n") return 1 - test_type_print(pool) - test_value_print(pool) - test_build_add(pool) - test_build_if_else(pool) - test_build_void(pool) - test_module_print(pool) - test_const_materialize(pool) - test_phi_block_args(pool) - test_mem_call_cast(pool) - test_globals(pool) - test_verify_valid(pool) - test_struct_global(pool) - test_alloca_align_switch_asm(pool) - test_vararg_vaarg_cmpxchg(pool) - test_named_struct(pool) - test_extractvalue_multi_asm(pool) + test_type_print(_sub_pool(pool)) + test_value_print(_sub_pool(pool)) + test_build_add(_sub_pool(pool)) + test_build_if_else(_sub_pool(pool)) + test_build_void(_sub_pool(pool)) + test_module_print(_sub_pool(pool)) + test_const_materialize(_sub_pool(pool)) + test_phi_block_args(_sub_pool(pool)) + test_mem_call_cast(_sub_pool(pool)) + test_globals(_sub_pool(pool)) + test_verify_valid(_sub_pool(pool)) + test_struct_global(_sub_pool(pool)) + test_alloca_align_switch_asm(_sub_pool(pool)) + test_vararg_vaarg_cmpxchg(_sub_pool(pool)) + test_named_struct(_sub_pool(pool)) + test_extractvalue_multi_asm(_sub_pool(pool)) return testcheck.end()