refactor: filter debug logs and deduplicate VPI loaders

Suppress DEBUG output at the default INFO level, share the VPI pre-registration walker, and share the .vpi read path between the annotation cache loaders. Source-only change: 53 added, 81 deleted (net -28 lines).
This commit is contained in:
TermiNexus committed 2026-11-02 13:24:30 +08:00
1 parent 634321a12b
commit 38a521fcd2
3 files changed
+59 -85

No files matched your search

+51 -81
View File
@@ -1071,6 +1071,33 @@ def _grow_vpi_ret_cache() -> int:
return 1
# _read_vpi_for_cache - read one .vpi file into a malloc buffer.
# status[0]: 0 = path/open/allocation failure, 1 = read attempted (None means empty).
def _read_vpi_for_cache(src_sha1: str, temp_dir: str, status: int*) -> bytes:
if status is not None: status[0] = 0
if src_sha1 is None or temp_dir is None: return None
vpi_path: str = _vpi_build_path(temp_dir, src_sha1, ".vpi")
if vpi_path is None: return None
f: io.File* = io.File(vpi_path, io.MODE.R)
if f.closed:
stdlib.free(vpi_path)
return None
vpi_buf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE)
if vpi_buf is None:
f.close()
stdlib.free(vpi_path)
return None
bytes_read: LONG = f.read_all(vpi_buf, VPI_READ_BUF_SIZE)
f.close()
stdlib.free(vpi_path)
if status is not None: status[0] = 1
if bytes_read <= 0:
stdlib.free(vpi_buf)
return None
if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0
return vpi_buf
# _ensure_vpi_ret_annot_loaded - lazily load a module's vpi stub return-annotation cache.
# On cache miss reads {temp_dir}/{sha1[0:2]}/{sha1}.vpi directly; idempotent.
def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int:
@@ -1088,28 +1115,11 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int:
for pre_i in range(int(_g_vpi_ret_count)):
pre_key: bytes = _g_vpi_ret_keys + pre_i * VPI_KEY_LEN
if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': return 1
# build {temp_dir}/{slice}/{sha1}.vpi — the slice must follow Config.Sha1SliceLevel,
# exactly like the writer (StubMergerCollect._sliced_path); hardcoding two hex chars
# makes every lookup miss when the project uses slice level 0 or 2.
vpi_path: str = _vpi_build_path(temp_dir, src_sha1, ".vpi")
if vpi_path is None: return 0
f: io.File* = io.File(vpi_path, io.MODE.R)
if f.closed:
stdlib.free(vpi_path)
return 0
vpi_buf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE)
if vpi_buf is None:
f.close()
stdlib.free(vpi_path)
return 0
bytes_read: LONG = f.read_all(vpi_buf, VPI_READ_BUF_SIZE)
f.close()
if bytes_read > 0:
if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0
# 单一入口:一次喂齐 ret / param / 逃逸摘要(见 _cache_vpi_annots_text 注释)
_cache_vpi_annots_text(vpi_buf, src_sha1)
st_r: int = 0
vpi_buf: bytes = _read_vpi_for_cache(src_sha1, temp_dir, &st_r)
if vpi_buf is None: return st_r
_cache_vpi_annots_text(vpi_buf, src_sha1)
stdlib.free(vpi_buf)
stdlib.free(vpi_path)
return 1
@@ -1703,27 +1713,11 @@ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int:
for pre_i in range(int(_g_vpi_param_count)):
pre_key: bytes = _g_vpi_param_keys + pre_i * VPI_PARAM_KEY_LEN
if pre_key[0] == s0 and pre_key[1] == s1 and string.strncmp(pre_key, src_sha1, sha1_len) == 0 and pre_key[sha1_len] == '.': return 1
# build {temp_dir}/{slice}/{sha1}.vpi — the slice must follow Config.Sha1SliceLevel,
# exactly like the writer (StubMergerCollect._sliced_path); hardcoding two hex chars
# makes every lookup miss when the project uses slice level 0 or 2.
vpi_path: str = _vpi_build_path(temp_dir, src_sha1, ".vpi")
if vpi_path is None: return 0
f: io.File* = io.File(vpi_path, io.MODE.R)
if f.closed:
stdlib.free(vpi_path)
return 0
vpi_buf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE)
if vpi_buf is None:
f.close()
stdlib.free(vpi_path)
return 0
bytes_read: LONG = f.read_all(vpi_buf, VPI_READ_BUF_SIZE)
f.close()
if bytes_read > 0:
if bytes_read < VPI_READ_BUF_SIZE: vpi_buf[bytes_read] = 0
_cache_vpi_param_annots_text(vpi_buf, src_sha1)
st_p: int = 0
vpi_buf: bytes = _read_vpi_for_cache(src_sha1, temp_dir, &st_p)
if vpi_buf is None: return st_p
_cache_vpi_param_annots_text(vpi_buf, src_sha1)
stdlib.free(vpi_buf)
stdlib.free(vpi_path)
return 1
@@ -2744,39 +2738,6 @@ def _ScanVpiDefaults(pool: memhub.MemBuddy*, vbuf: bytes, buf_len: sizet, sha1:
stdlib.free(strs)
return reg
# PreRegisterVpiDefaults - 在翻译开始前,把 store 里所有模块的 .vpi 缺省值一次性登记
def PreRegisterVpiDefaults(pool: memhub.MemBuddy*, temp_dir: str) -> int:
"""预登记所有模块 .vpi 里的函数缺省值;返回登记的函数个数"""
if pool is None or temp_dir is None: return 0
n: int = StubMergerStore.GetSha1StoreCount()
if n <= 0: return 0
sha1_arr: bytes = StubMergerStore.GetSha1StoreArrPtr()
if sha1_arr is None: return 0
total_reg: int = 0
si: int
for si in range(int(n)):
sha1: str = sha1_arr + sizet(si) * 17
if sha1[0] == '\0': continue
fpath: str = _vpi_build_path(temp_dir, sha1, ".vpi")
if fpath is None: continue
vf: io.File* = io.File(fpath, io.MODE.R)
stdlib.free(fpath)
if vf.closed: continue
vbuf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE)
if vbuf is None:
vf.close()
continue
nrd: LONG = vf.read_all(vbuf, VPI_READ_BUF_SIZE)
vf.close()
if nrd <= 0:
stdlib.free(vbuf)
continue
if nrd < VPI_READ_BUF_SIZE: vbuf[nrd] = 0
total_reg += _ScanVpiDefaults(pool, vbuf, string.strlen(vbuf), sha1)
stdlib.free(vbuf)
return total_reg
# 单个 .vpi 的枚举成员上限(与 ENUM_MEMBER_MAX 同量级)
define VPI_ENUM_MEMBER_MAX = 128
@@ -2908,10 +2869,8 @@ def _ScanVpiEnumsText(pool: memhub.MemBuddy*, vbuf: bytes, vlen: sizet, sha1: st
return reg
# PreRegisterVpiEnums - 翻译开始前,把所有模块 .vpi 里的 `enum X:` 一次性登记进 EnumTable。
# 与 PreRegisterVpiDefaults 同理:消除"谁先注入谁登记"的时序依赖。
def PreRegisterVpiEnums(pool: memhub.MemBuddy*, temp_dir: str) -> int:
"""预登记所有模块 .vpi 里的枚举;返回登记的枚举个数"""
# _PreRegisterVpiFiles - run one pre-registration scanner over all registered .vpi files.
def _PreRegisterVpiFiles(pool: memhub.MemBuddy*, temp_dir: str, scan_enums: int) -> int:
if pool is None or temp_dir is None: return 0
n: int = StubMergerStore.GetSha1StoreCount()
if n <= 0: return 0
@@ -2937,12 +2896,24 @@ def PreRegisterVpiEnums(pool: memhub.MemBuddy*, temp_dir: str) -> int:
stdlib.free(vbuf)
continue
if nrd < VPI_READ_BUF_SIZE: vbuf[nrd] = 0
total_reg += _ScanVpiEnumsText(pool, vbuf, string.strlen(vbuf), sha1)
if scan_enums != 0: total_reg += _ScanVpiEnumsText(pool, vbuf, string.strlen(vbuf), sha1)
else: total_reg += _ScanVpiDefaults(pool, vbuf, string.strlen(vbuf), sha1)
stdlib.free(vbuf)
return total_reg
# _VpiParamCountAndVararg - 数参数个数;含 *args / **kwargs 时返回 -1(调用方跳过 arity 校验)
# PreRegisterVpiDefaults - pre-register defaults from all registered .vpi files.
def PreRegisterVpiDefaults(pool: memhub.MemBuddy*, temp_dir: str) -> int:
"""Pre-register .vpi default values; returns the number of registrations."""
return _PreRegisterVpiFiles(pool, temp_dir, 0)
# PreRegisterVpiEnums - pre-register enums from all registered .vpi files.
def PreRegisterVpiEnums(pool: memhub.MemBuddy*, temp_dir: str) -> int:
"""Pre-register .vpi enums; returns the number of registrations."""
return _PreRegisterVpiFiles(pool, temp_dir, 1)
def _VpiParamCountAndVararg(vbuf: bytes, ps: sizet, pe: sizet) -> int:
"""Number of parameters; -1 when the list contains *args/**kwargs."""
n: int = VpiText.ParamCount(vbuf, ps, pe)
@@ -2951,7 +2922,6 @@ def _VpiParamCountAndVararg(vbuf: bytes, ps: sizet, pe: sizet) -> int:
return n
# LookupSignDefaultsByName - 直接在定义模块 .vpi 文本里查一个函数/方法的缺省参数快照
# 与 PreRegisterVpiDefaults 的区别:不登记进全局表,只按名字现查现用(表键不可靠时的兜底)。
# 返回 (参数个数 << 8) | 缺省值个数;-1 = 未找到或有不可重建的缺省值。
# --- signature range cache --------------------------------------------------
# LookupSignDefaultsByName re-scanned the whole .vpi text per query (one
+2
View File
@@ -90,6 +90,8 @@ novirtual class Logger:
# _log - core log output with segmented coloring (prefix symbol / level tag / message).
# Format: ├ LEVEL: msg or ├ LEVEL[category]: msg.
def _log(self, level: int, prefix_sym: str, level_str: str, msg: str, sym_color: WORD, level_color: WORD, category: str = "") -> int:
# Default level is INFO; DEBUG messages stay silent unless the level is lowered.
if level < self._level: return 0
# Color the prefix symbol
self._set_color(sym_color)
stdio.printf("%s ", prefix_sym)
+6 -4
View File
@@ -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.
- `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.
- `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`.
@@ -124,9 +124,11 @@ The following duplicate implementations were merged or redirected:
- `ViperBuild`: one list-join helper.
- LSP: removed duplicate `_Doc`, `_Cat`, `_Trim`, and `_HexVal` implementations; `_HashText` keeps its local None semantics.
Measured source-only reduction for this batch: **235 added / 793 deleted = net -558 lines** (excluding `App/main.vp` and this report).
Measured source-only reduction for the main consolidation batch: **235 added / 793 deleted = net -558 lines** (excluding `App/main.vp` and this report).
Remaining candidates: `VpiReader` annotation-file scanners and cache loaders, `BuildPipeline` MLIR path setup, `LSP _SliceStr/_ByteAt`, and the list/dict iteration helpers.
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.
---
@@ -140,7 +142,7 @@ Remaining candidates: `VpiReader` annotation-file scanners and cache loaders, `B
### P1: log level is not enforced
`VLogger` stores `_level` but `_log` never compares it, so `VLogger.debug` prints at the default INFO level. Either add `if level < self._level: return 0` at the start of `_log`, or remove the two debug call sites.
Applied: `VLogger._log` now returns early when `level < self._level`, so DEBUG messages stay silent at the default INFO level. The two debug call sites remain available for diagnostic builds.
### P2: verbose but intentional