diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index e381e47..92e7d75 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -121,7 +121,6 @@ define VPI_IDX_FNV_OFFSET = 2166136261 define VPI_IDX_FNV_PRIME = 16777619 define VPI_IDX_FNV_MASK = 4294967295 -# v3 跨模块逃逸摘要缓存(.vpi 行尾 `# esc= ret=`,由 StubGen.Converter._PyiFunction 写出)。 # 键 = "{sha1}.{Class}.{method}"(方法)或 "{sha1}.{func}"(模块级函数); # 值打包:低 32 位 = 形参逃逸掩码,高 32 位 = 返回借用位。无逃逸/无返回借用的 def 不写条目, # 因此"查不到"即"无摘要"(调用点保守放行),与本地表口径一致。 @@ -137,7 +136,6 @@ _g_vpi_wf_keys: bytes = None _g_vpi_wf_vals: sizet* = None _g_vpi_wf_count: int = 0 # 跨模块常量特化(P3 收尾):同一函数可有多条 `escg=`(打包 p|k|m,见 StructGenMixin._PackEscapeClear), -# 所以是"一键多行"表:键列与 wf 表同构,值列是打包整数。 define VPI_ESG_MAX = 8192 define VPI_ESG_KEY_LEN = 224 # 常量环境的形参位上限:必须与 StructGenMixin.EC_ENV_MAX 一致(越界位一律不信) @@ -1124,7 +1122,6 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int: # _cache_vpi_esc_clears_text - 抽取行尾**所有** `escg=` 标记(跨模块常量特化)。 -# 与 wf 表同构,但同一行可有多条(一条一个打包值),故是"一键多行"。值 = p|k|m 打包整数 # (见 StructGenMixin._PackEscapeClear:p=守卫形参位、k=常量、m=可清掉的位掩码)。 def _cache_vpi_esc_clears_text(vpi_buf: bytes, src_sha1: str) -> int: """抽取 vpi 行尾的 escg= 标记进缓存;1=处理完成 / 0=缓冲区或分配失败""" @@ -1395,18 +1392,27 @@ def _cache_vpi_annots_text(vpi_buf: bytes, src_sha1: str) -> int: return 1 -# _cache_vpi_escape_annots_text - extract the trailing `# esc= ret=` markers. -# v3 跨模块逃逸摘要:不依赖 AST,按行扫描(与 _cache_vpi_return_annots_text 同构)。 -def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: - """抽取 vpi 行尾逃逸摘要标记进缓存;1=处理完成 / 0=缓冲区或分配失败""" +# _cache_vpi_marker_annots_text - scan .vpi def lines and cache per-method markers. +# kind 0 = escape summary (`# esc= ret=`), kind 1 = willFree (`# ... wf=`). +def _cache_vpi_marker_annots_text(vpi_buf: bytes, src_sha1: str, kind: int) -> int: global _g_vpi_esc_keys, _g_vpi_esc_vals, _g_vpi_esc_count + global _g_vpi_wf_keys, _g_vpi_wf_vals, _g_vpi_wf_count if vpi_buf is None or src_sha1 is None: return 0 - if _g_vpi_esc_keys is None: - _g_vpi_esc_keys = stdlib.malloc(VPI_ESC_MAX * VPI_ESC_KEY_LEN) - _g_vpi_esc_vals = sizet*(stdlib.malloc(VPI_ESC_MAX * 8)) - if _g_vpi_esc_keys is None or _g_vpi_esc_vals is None: return 0 - string.memset(_g_vpi_esc_keys, 0, VPI_ESC_MAX * VPI_ESC_KEY_LEN) - string.memset(_g_vpi_esc_vals, 0, VPI_ESC_MAX * 8) + if kind == 0: + if _g_vpi_esc_keys is None: + _g_vpi_esc_keys = stdlib.malloc(VPI_ESC_MAX * VPI_ESC_KEY_LEN) + _g_vpi_esc_vals = sizet*(stdlib.malloc(VPI_ESC_MAX * 8)) + if _g_vpi_esc_keys is None or _g_vpi_esc_vals is None: return 0 + string.memset(_g_vpi_esc_keys, 0, VPI_ESC_MAX * VPI_ESC_KEY_LEN) + string.memset(_g_vpi_esc_vals, 0, VPI_ESC_MAX * 8) + else: + if _g_vpi_wf_keys is None: + _g_vpi_wf_keys = stdlib.malloc(VPI_WF_MAX * VPI_WF_KEY_LEN) + _g_vpi_wf_vals = sizet*(stdlib.malloc(VPI_WF_MAX * 8)) + if _g_vpi_wf_keys is None or _g_vpi_wf_vals is None: return 0 + string.memset(_g_vpi_wf_keys, 0, VPI_WF_MAX * VPI_WF_KEY_LEN) + string.memset(_g_vpi_wf_vals, 0, VPI_WF_MAX * 8) + sha1_len: sizet = string.strlen(src_sha1) buf_len: sizet = string.strlen(vpi_buf) cur_cls: bytes = None @@ -1418,7 +1424,6 @@ def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: i: sizet = ls while i < le and vpi_buf[i] == ' ': i += 1 if i < le: - # class X: -> 记录当前类上下文(与方法键一致;兼容 virtual/novirtual 前缀) cls_off_e: int = _vpi_class_name_offset(vpi_buf, i, le) if cls_off_e >= 0: cstart: sizet = sizet(cls_off_e) @@ -1430,34 +1435,65 @@ def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: if cur_cls is not None: string.strncpy(cur_cls, vpi_buf + cstart, cend - cstart) cur_cls[cend - cstart] = '\0' - # def name(...) ... # esc= ret= elif le - i >= 4 and _vpi_func_name_offset(vpi_buf, i, le) >= 0: - # 模块级函数(无缩进)清掉类上下文,避免上一类泄漏 if i == ls and cur_cls is not None: stdlib.free(cur_cls) cur_cls = None - # 找同行 "# esc=" 标记 mark: sizet = le + hm: sizet = le j: sizet = i - while j + 6 <= le: - if vpi_buf[j] == '#' and vpi_buf[j + 1] == ' ' and string.strncmp(vpi_buf + j + 2, "esc=", 4) == 0: - mark = j + while j < le: + if vpi_buf[j] == '#': + hm = j break j += 1 - if mark < le: - kp: sizet = mark + 6 - esc_v: int = 0 - while kp < le and vpi_buf[kp] >= '0' and vpi_buf[kp] <= '9': - esc_v = esc_v * 10 + (int(vpi_buf[kp]) - 48) - kp += 1 - ret_v: int = 0 - while kp < le and vpi_buf[kp] != 'e': kp += 1 - if kp + 4 <= le: - kp += 4 + esc_v: int = 0 + ret_v: int = 0 + wf_v: int = 0 + if kind == 0: + j2: sizet = i + while j2 + 6 <= le: + if vpi_buf[j2] == '#' and vpi_buf[j2 + 1] == ' ' and string.strncmp(vpi_buf + j2 + 2, "esc=", 4) == 0: + mark = j2 + break + j2 += 1 + if mark < le: + kp: sizet = mark + 6 while kp < le and vpi_buf[kp] >= '0' and vpi_buf[kp] <= '9': - ret_v = ret_v * 10 + (int(vpi_buf[kp]) - 48) + esc_v = esc_v * 10 + (int(vpi_buf[kp]) - 48) kp += 1 - if (esc_v != 0 or ret_v != 0) and _g_vpi_esc_count < VPI_ESC_MAX: + while kp < le and vpi_buf[kp] != 'e': kp += 1 + if kp + 4 <= le: + kp += 4 + while kp < le and vpi_buf[kp] >= '0' and vpi_buf[kp] <= '9': + ret_v = ret_v * 10 + (int(vpi_buf[kp]) - 48) + kp += 1 + else: + if hm < le: + j3: sizet = hm + 1 + while j3 + 3 <= le: + if vpi_buf[j3] == 'w' and vpi_buf[j3 + 1] == 'f' and vpi_buf[j3 + 2] == '=': + mark = j3 + break + j3 += 1 + if mark < le: + kp2: sizet = mark + 3 + while kp2 < le and vpi_buf[kp2] >= '0' and vpi_buf[kp2] <= '9': + wf_v = wf_v * 10 + (int(vpi_buf[kp2]) - 48) + kp2 += 1 + + has_marker: int = 0 + if kind == 0: + if esc_v != 0 or ret_v != 0: has_marker = 1 + else: + if wf_v != 0: has_marker = 1 + if has_marker != 0: + can_store: int = 0 + if kind == 0: + if _g_vpi_esc_count < VPI_ESC_MAX: can_store = 1 + else: + if _g_vpi_wf_count < VPI_WF_MAX: can_store = 1 + if can_store != 0: dstart: sizet = sizet(_vpi_func_name_offset(vpi_buf, i, le)) dend: sizet = dstart while dend < le and vpi_buf[dend] != '(': dend += 1 @@ -1466,7 +1502,12 @@ def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: cls_len_e: sizet = 0 if cur_cls is not None: cls_len_e = string.strlen(cur_cls) key_len_e: sizet = sha1_len + 1 + cls_len_e + 1 + mname_len - if key_len_e < VPI_ESC_KEY_LEN: + key_ok: int = 0 + if kind == 0: + if key_len_e < VPI_ESC_KEY_LEN: key_ok = 1 + else: + if key_len_e < VPI_WF_KEY_LEN: key_ok = 1 + if key_ok != 0: mname_buf_e: bytes = stdlib.malloc(mname_len + 1) key_buf_e: bytes = stdlib.malloc(key_len_e + 1) if mname_buf_e is not None and key_buf_e is not None: @@ -1474,9 +1515,14 @@ def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: mname_buf_e[mname_len] = '\0' if cur_cls is not None: viperlib.snprintf(key_buf_e, key_len_e + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf_e) else: viperlib.snprintf(key_buf_e, key_len_e + 1, "%s.%s", src_sha1, mname_buf_e) - string.strcpy(_g_vpi_esc_keys + sizet(_g_vpi_esc_count) * VPI_ESC_KEY_LEN, key_buf_e) - _g_vpi_esc_vals[_g_vpi_esc_count] = sizet(esc_v) | (sizet(ret_v) << 32) - _g_vpi_esc_count += 1 + if kind == 0: + string.strcpy(_g_vpi_esc_keys + sizet(_g_vpi_esc_count) * VPI_ESC_KEY_LEN, key_buf_e) + _g_vpi_esc_vals[_g_vpi_esc_count] = sizet(esc_v) | (sizet(ret_v) << 32) + _g_vpi_esc_count += 1 + else: + string.strcpy(_g_vpi_wf_keys + sizet(_g_vpi_wf_count) * VPI_WF_KEY_LEN, key_buf_e) + _g_vpi_wf_vals[_g_vpi_wf_count] = sizet(wf_v) + _g_vpi_wf_count += 1 if mname_buf_e is not None: stdlib.free(mname_buf_e) if key_buf_e is not None: stdlib.free(key_buf_e) pos = le + 1 @@ -1484,6 +1530,12 @@ def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: return 1 +# _cache_vpi_escape_annots_text - cache the escape summary markers. +def _cache_vpi_escape_annots_text(vpi_buf: bytes, src_sha1: str) -> int: + """Cache escape-summary markers from one .vpi text.""" + return _cache_vpi_marker_annots_text(vpi_buf, src_sha1, 0) + + # _lookup_vpi_escape_packed - query the cross-module escape summary cache (v3). def _lookup_vpi_escape_packed(src_sha1: str, cls_name: str, method_name: str) -> int: """查跨模块逃逸摘要;返回打包值(低32位 mask | ret<<32),0 = 无摘要""" @@ -1504,94 +1556,10 @@ def _lookup_vpi_escape_packed(src_sha1: str, cls_name: str, method_name: str) -> return res -# _cache_vpi_willfree_annots_text - extract the trailing `wf=` marker (P2 willFree). -# 与逃逸摘要同构:不依赖 AST,按行扫描;只在有 wf 标记的 def 上建条目。 +# _cache_vpi_willfree_annots_text - cache the P2 willFree markers. def _cache_vpi_willfree_annots_text(vpi_buf: bytes, src_sha1: str) -> int: - """抽取 vpi 行尾 P2 willFree 标记(`# ... wf=`)进缓存;1=处理完成 / 0=缓冲区或分配失败""" - global _g_vpi_wf_keys, _g_vpi_wf_vals, _g_vpi_wf_count - if vpi_buf is None or src_sha1 is None: return 0 - if _g_vpi_wf_keys is None: - _g_vpi_wf_keys = stdlib.malloc(VPI_WF_MAX * VPI_WF_KEY_LEN) - _g_vpi_wf_vals = sizet*(stdlib.malloc(VPI_WF_MAX * 8)) - if _g_vpi_wf_keys is None or _g_vpi_wf_vals is None: return 0 - string.memset(_g_vpi_wf_keys, 0, VPI_WF_MAX * VPI_WF_KEY_LEN) - string.memset(_g_vpi_wf_vals, 0, VPI_WF_MAX * 8) - sha1_len: sizet = string.strlen(src_sha1) - buf_len: sizet = string.strlen(vpi_buf) - cur_cls: bytes = None - pos: sizet = 0 - while pos < buf_len: - ls: sizet = pos - le: sizet = pos - while le < buf_len and vpi_buf[le] != '\n': le += 1 - i: sizet = ls - while i < le and vpi_buf[i] == ' ': i += 1 - if i < le: - # class X: -> 记录当前类上下文(与方法键一致;兼容 virtual/novirtual 前缀) - cls_off_e: int = _vpi_class_name_offset(vpi_buf, i, le) - if cls_off_e >= 0: - cstart: sizet = sizet(cls_off_e) - cend: sizet = cstart - while cend < le and vpi_buf[cend] != ':' and vpi_buf[cend] != ' ' and vpi_buf[cend] != '(': cend += 1 - if cend > cstart: - if cur_cls is not None: stdlib.free(cur_cls) - cur_cls = stdlib.malloc(cend - cstart + 1) - if cur_cls is not None: - string.strncpy(cur_cls, vpi_buf + cstart, cend - cstart) - cur_cls[cend - cstart] = '\0' - # def name(...) ... # [esc= ret=] wf= - elif le - i >= 4 and _vpi_func_name_offset(vpi_buf, i, le) >= 0: - # 模块级函数(无缩进)清掉类上下文,避免上一类泄漏 - if i == ls and cur_cls is not None: - stdlib.free(cur_cls) - cur_cls = None - # 只在注释段里找 "wf=":避开参数名(如 def f(wf: int)) - mark: sizet = le - hm: sizet = le - j: sizet = i - while j < le: - if vpi_buf[j] == '#': - hm = j - break - j += 1 - if hm < le: - j2: sizet = hm + 1 - while j2 + 3 <= le: - if vpi_buf[j2] == 'w' and vpi_buf[j2 + 1] == 'f' and vpi_buf[j2 + 2] == '=': - mark = j2 - break - j2 += 1 - if mark < le: - kp: sizet = mark + 3 - wf_v: int = 0 - while kp < le and vpi_buf[kp] >= '0' and vpi_buf[kp] <= '9': - wf_v = wf_v * 10 + (int(vpi_buf[kp]) - 48) - kp += 1 - if wf_v != 0 and _g_vpi_wf_count < VPI_WF_MAX: - dstart: sizet = sizet(_vpi_func_name_offset(vpi_buf, i, le)) - dend: sizet = dstart - while dend < le and vpi_buf[dend] != '(': dend += 1 - if dend > dstart: - mname_len: sizet = dend - dstart - cls_len_w: sizet = 0 - if cur_cls is not None: cls_len_w = string.strlen(cur_cls) - key_len_w: sizet = sha1_len + 1 + cls_len_w + 1 + mname_len - if key_len_w < VPI_WF_KEY_LEN: - mname_buf_w: bytes = stdlib.malloc(mname_len + 1) - key_buf_w: bytes = stdlib.malloc(key_len_w + 1) - if mname_buf_w is not None and key_buf_w is not None: - string.strncpy(mname_buf_w, vpi_buf + dstart, mname_len) - mname_buf_w[mname_len] = '\0' - if cur_cls is not None: viperlib.snprintf(key_buf_w, key_len_w + 1, "%s.%s.%s", src_sha1, cur_cls, mname_buf_w) - else: viperlib.snprintf(key_buf_w, key_len_w + 1, "%s.%s", src_sha1, mname_buf_w) - string.strcpy(_g_vpi_wf_keys + sizet(_g_vpi_wf_count) * VPI_WF_KEY_LEN, key_buf_w) - _g_vpi_wf_vals[_g_vpi_wf_count] = sizet(wf_v) - _g_vpi_wf_count += 1 - if mname_buf_w is not None: stdlib.free(mname_buf_w) - if key_buf_w is not None: stdlib.free(key_buf_w) - pos = le + 1 - if cur_cls is not None: stdlib.free(cur_cls) - return 1 + """Cache willFree markers from one .vpi text.""" + return _cache_vpi_marker_annots_text(vpi_buf, src_sha1, 1) # _lookup_vpi_willfree - query the cross-module P2 willFree cache (key shape = escape summary). diff --git a/DEAD_CODE_REPORT.md b/DEAD_CODE_REPORT.md index 5a4728a..0989433 100644 --- a/DEAD_CODE_REPORT.md +++ b/DEAD_CODE_REPORT.md @@ -114,7 +114,7 @@ Retained: `ClassGenEnum.RenumTableDump` is referenced from a diagnostic f-string The following duplicate implementations were merged or redirected: - `Phase2`: one directory walker for `.vp` and `.s` sources. -- `VpiReader`: shared `_vpi_method_key` for all cached-annotation lookups, a shared pre-registration walker for defaults/enums, and a shared `.vpi` read helper for the two annotation cache loaders. +- `VpiReader`: shared `_vpi_method_key` for all cached-annotation lookups, a shared pre-registration walker for defaults/enums, a shared `.vpi` read helper for the two annotation cache loaders, and one marker scanner for escape/willFree annotations. - `StubMergerStore`: shared store initialization/append and alias parsing. - `AssignGenMixin` / `ExprGenCdef`: one `TypeGenCDef.NormalizeDefineBits`. - `AssignGenMixin` / `ExprGenCls`: removed the weaker duplicate class-annotation helpers; calls now use `ExprGenCls`. @@ -128,7 +128,9 @@ Measured source-only reduction for the main consolidation batch: **235 added / 7 Follow-up batch: VLogger level filtering and the VpiReader pre-registration/read helpers, **53 added / 81 deleted = net -28 lines**. -Remaining candidates: `VpiReader` escape/willfree annotation scanners, `BuildPipeline` MLIR path setup, `LSP _SliceStr/_ByteAt`, and the list/dict iteration helpers. +Scanner batch: one VpiReader marker scanner for escape/willFree annotations, **91 added / 123 deleted = net -32 lines**. + +Remaining candidates: `BuildPipeline` MLIR path setup, `LSP _SliceStr/_ByteAt`, the list/dict iteration helpers, and the nested-function rescan walkers. ---