diff --git a/App/lib/core/Gen/Call/CallGenCall.vp b/App/lib/core/Gen/Call/CallGenCall.vp index e2eb15a..68fb7ff 100644 --- a/App/lib/core/Gen/Call/CallGenCall.vp +++ b/App/lib/core/Gen/Call/CallGenCall.vp @@ -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) diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index c8bc623..209f687 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -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),则对象与本帧同命、并不真的逃逸 → 可清。