fix(lifetime): 方法路径补上"同命裁剪"(此前缺失)—— h.set_q(l) 不该报
现场:h: S* = new heap slife S()(生命期本就是 FRAME:作用域出口释放)+ l 是栈数组; h.set_q(l) 却报"escaping method parameter"。根因:同命裁剪只做在模块级函数路径,方法路径一直没接 (此前已明确告知"还差一半")。 新增 CallGenMixin._FrameArgsEscapeClearsMethod:位 0 = 接收者(self)、位 (i+1) = 用户第 i 个实参; 某位可清 ⇔ 该位对应实参是 FRAME/VALUE 且其余全部实参(含接收者)也在本帧。 CallGenCall 方法路径在 refine 之后、指令最终裁决之前套用;硬位仍用 get_param_escapes_hard_method 排除。 构造器路径暂未接(__init__ 的 self 是"正在构造的对象",此处拿不到接收者 AST 变量)。
This commit is contained in:
1 parent
6000734704
commit
bf5ecd7668
2 files changed
+45
-1
No files matched your search
@@ -574,7 +574,20 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
# 跨过程常量特化(P3 收尾):同文件能拿到方法体时,用常量实参重算摘要(形参位含 self 偏移)
|
||||
if esc_mask_mc != 0:
|
||||
can_rf: sizet = len(cargs_mc)
|
||||
esc_mask_mc = GenApi.refine_escape_mask_method(pool, class_name, method_name, cargs_mc, can_rf, esc_mask_mc)
|
||||
esc_mask_mc = GenApi.refine_escape_mask_method(pool, class_name, method_name, cargs_mc, can_rf, esc_mask_mc)
|
||||
# 同命裁剪(**方法路径,此前缺失**):只清"写进形参对象字段"那一类位 —— 若其余实参(含
|
||||
# 接收者)也都在本帧,则接收者与本帧同命、并不真的逃逸。现场:`h.set_q(l)`,h 是
|
||||
# `new heap slife S()`(生命期本就是 FRAME)、l 是栈数组 → 两都在本帧 → 不该报。
|
||||
if esc_mask_mc != 0:
|
||||
hard_mc: int = GenApi.get_param_escapes_hard_method(pool, class_name, method_name)
|
||||
fld_mc: int = esc_mask_mc & (~hard_mc)
|
||||
if fld_mc != 0:
|
||||
recv_mc: ast.AST* = None
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
recv_mc = ast.Attribute*(cl.func).value
|
||||
can_sf: sizet = len(cargs_mc)
|
||||
cl_sfm: int = self.Gen.CallGen._FrameArgsEscapeClearsMethod(trans, recv_mc, cargs_mc, can_sf, fld_mc)
|
||||
if cl_sfm != 0: esc_mask_mc = esc_mask_mc & (~cl_sfm)
|
||||
# 声明式指令最终裁决(@life(escape/noescape):unsafe 但强制),在推断/回退之后最后套用
|
||||
f_mc: int = GenApi.get_param_escape_force_method(pool, class_name, method_name)
|
||||
n_mc: int = GenApi.get_param_noescape_force_method(pool, class_name, method_name)
|
||||
|
||||
@@ -60,6 +60,37 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
return 0
|
||||
|
||||
|
||||
# _FrameArgsEscapeClearsMethod - 方法调用版"同命"裁剪(与函数版同口径,但位有 self 偏移)
|
||||
# 位 0 = 接收者(self),位 (i+1) = 用户第 i 个实参。
|
||||
# 某位可清 ⇔ 该位对应的实参是帧生命期(FRAME/VALUE),且**其余全部实参(含接收者)也在本帧**。
|
||||
# 现场:`h.set_q(l)` 里 h = `new heap slife S()`(生命期本就是 FRAME:作用域出口释放)、
|
||||
# l 是栈数组 → 两都在本帧 → 不该报。
|
||||
def _FrameArgsEscapeClearsMethod(self, trans: HT.Translator*, recv_node: ast.AST*, cargs: list[ast.AST*]*, can: sizet, only_fld: int) -> int:
|
||||
"""返回方法调用中可安全清掉的位掩码(0 = 一位都清不掉)"""
|
||||
if trans is None or only_fld == 0: return 0
|
||||
cleared: int = 0
|
||||
bi: int = 1
|
||||
while bi <= int(can):
|
||||
if ((only_fld >> bi) & 1) == 0:
|
||||
bi += 1
|
||||
continue
|
||||
all_frame: int = 1
|
||||
if recv_node is not None:
|
||||
lr: int = self.Gen.AssignGen.life_of_expr(trans, recv_node, None)
|
||||
if lr != GenTypes.LIFE_FRAME and lr != GenTypes.LIFE_VALUE: all_frame = 0
|
||||
j: sizet = 0
|
||||
while j < can:
|
||||
if all_frame == 0: break
|
||||
if int(j) != bi - 1:
|
||||
a_j: ast.AST* = cargs.get(j)
|
||||
if a_j is not None:
|
||||
lj: int = self.Gen.AssignGen.life_of_expr(trans, a_j, None)
|
||||
if lj != GenTypes.LIFE_FRAME and lj != GenTypes.LIFE_VALUE: all_frame = 0
|
||||
j += 1
|
||||
if all_frame != 0: cleared = cleared | (1 << bi)
|
||||
bi += 1
|
||||
return cleared
|
||||
|
||||
# _FrameArgsEscapeClears - "同命"精化(P3 同命规则在**调用点**的对应物):
|
||||
# 候选位 only_fld 只由"写进某个**形参对象**的字段"造成;若调用点交出的其它实参也都在本帧
|
||||
# (LIFE_FRAME)或纯值语义(LIFE_VALUE),则对象与本帧同命、并不真的逃逸 → 可清。
|
||||
|
||||
Reference in new issue
Block a user