feat(gen): 协程体里的 new heap slife fail-fast(释放点无法确定)
AsyncGenMixin 的状态机会把协程 body 拆成多个 state 块并多次转译,编译器无法确定 slife 的释放点;此前是静默漏释放。新增锚点 trans._coro_body_func(Translator 字段 + init 置 None),只在 body 翻译期间由 translate_async_function 设置并保存/恢复旧值;_translate_new_expr 以**函数对象同一性**(_coro_body_func == _cur_func)判定并 fatal_error(LifetimeError)。嵌套普通函数会换掉 _cur_func 故不误报;new stack 与 hlife 不受影响。
This commit is contained in:
1 parent
2178970ff7
commit
70390858d8
3 files changed
+20
No files matched your search
@@ -883,7 +883,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
trans._cur_builder = builder
|
||||
seg_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(state_bbs[0])
|
||||
mlirlite.position_at_end(builder, seg_bb)
|
||||
# M3 硬约束锚点:登记"正在翻译其 body 的协程函数",CallGenCtor._translate_new_expr 据此对
|
||||
# 协程体内的 `new heap slife` fail-fast(协程体被状态机拆分,释放点无法确定)。
|
||||
# 保存/恢复旧值:协程里再定义协程时不会把外层的标记冲掉。
|
||||
old_coro_body: mlirlite.Function* = trans._coro_body_func
|
||||
trans._coro_body_func = func
|
||||
self._handle_segment(trans, builder, pool, mod, fd.children)
|
||||
trans._coro_body_func = old_coro_body
|
||||
# body fell through -> implicit return (ret=0 + done=1 + br exit)
|
||||
if mlirlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
zret: mlirlite.Value* = mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -333,6 +333,15 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if pool is None or builder is None or new_node is None or trans is None: return None
|
||||
src: int = new_node.Source
|
||||
life: int = new_node.Life
|
||||
# M3 硬约束:async 函数体被状态机拆成多个 state 块,释放点无法确定 →
|
||||
# `new heap slife`(编译器独占释放的那种)在协程体里 fail-fast,绝不让"登记了却永不释放"
|
||||
# 静默通过。判定用**函数对象同一性**(trans._coro_body_func,见 AsyncGenMixin 的登记点):
|
||||
# 协程体内嵌套的普通函数会换掉 _cur_func,所以不会误报。
|
||||
# `new stack`(帧内 alloca,无需释放)与 `hlife`(自行管理)不受影响。
|
||||
if trans._coro_body_func is not None and trans._cur_func is not None:
|
||||
if uint64(trans._coro_body_func) == uint64(trans._cur_func) and self._new_is_owned_heap(new_node) != 0:
|
||||
self.Gen.TypeGenErr.fatal_error(new_node, "`new heap slife ...` cannot be used inside an async function body: the coroutine body is split into state blocks, so the compiler cannot place the release point; use `new heap hlife ...` (and manage it yourself), or move the `slife` allocation into a regular function", "LifetimeError")
|
||||
return None
|
||||
# 缺省规则(§3.2 / D3):来源缺省 = heap;生命期缺省由来源决定
|
||||
# stack → slife(帧生命期;故 `new stack T(...)` 不写 slife 也等效)
|
||||
# heap / memgr → hlife(自由生命期)
|
||||
|
||||
@@ -76,6 +76,10 @@ novirtual class Translator:
|
||||
_coro_frame: mlirlite.Value*
|
||||
_coro_next_state: int
|
||||
_coro_nseg: int
|
||||
# M3 硬约束锚点:正在翻译其 body 的协程函数(= create_/resume_ 那个合成函数)。
|
||||
# 只有 body 翻译期间非 None,且与 _cur_func 同一对象才算"在协程体里"——嵌套的普通函数
|
||||
# 会换掉 _cur_func,故不会误报。用于禁止协程体内的 `new heap slife`(释放点无法确定)。
|
||||
_coro_body_func: mlirlite.Function*
|
||||
# M2: async parameter table (char* array, 8 bytes/item) + pre-scan counts
|
||||
_coro_params: str
|
||||
_coro_param_count: int
|
||||
@@ -283,6 +287,7 @@ novirtual class Translator:
|
||||
self._coro_frame = None
|
||||
self._coro_next_state = 1
|
||||
self._coro_nseg = 0
|
||||
self._coro_body_func = None
|
||||
self._coro_params = None
|
||||
self._coro_param_count = 0
|
||||
self._coro_hoist_count = 0
|
||||
|
||||
Reference in new issue
Block a user