refactor: share VPI escape and willFree scanners
Replace the two near-identical VPI annotation line scanners with one marker scanner parameterized by annotation kind. Source-only change: 91 added, 123 deleted (net -32 lines).
This commit is contained in:
1 parent
38a521fcd2
commit
9e0729b855
2 files changed
+95
-125
No files matched your search
@@ -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=<mask> ret=<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=<packed>` 标记(跨模块常量特化)。
|
||||
# 与 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=<mask> ret=<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=<mask> ret=<ret>`), kind 1 = willFree (`# ... wf=<mask>`).
|
||||
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=<mask> ret=<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=<mask>` 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=<mask>`)进缓存;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=<mask> ret=<ret>] wf=<mask>
|
||||
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).
|
||||
|
||||
+4
-2
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user