fix(tpv): 修常量折成0致alloc(0)与多处fail-fast,并落地热点优化
TypeGenCDef: CDefine 表名深拷贝(vpi 注入名为零拷贝指针且 vpi_buf 提前释放,悬空名致常量查出错误值 0) VpiReader: 模块级 SHA1_LEN(16) 改名 SHA1_HEX_LEN,消除与 Phase1.SHA1_LEN(17) 的跨模块同名冲突 CallGenCall: 实参翻译失败/漏传必需实参改 fail-fast,禁用零值兜底(堵住 SHA1_LEN 未解析变 alloc 0 的通路) MatchGenMixin: 序列 match 的 case _ 分支补容量守卫(原先会越界写穿 pool 块、破坏空闲链) Phase1Main/Phase1Scan: 预扫描缓冲分配失败改 fail-fast;加临时取证打点 CallGenBase: find_func_in_module 4 趟链表扫描合并为 2 趟 ImportsGenMixin: import 查找加哈希索引(键为 NUL 结尾副本,未命中回退原扫描) TypeGenBase/TypeGenResolve: 库 typedef 按模块一次性门禁与缓存 VpiReader: vpi 注解解析补 rowptr[T] 分支
This commit is contained in:
1 parent
af2c66e7d7
commit
0dd7511a9b
11 files changed
+666
-136
No files matched your search
@@ -437,6 +437,59 @@ def RunPhase1(mb: rowptr[memhub.MemBuddy], includes_dir: str, temp_dir: str,
|
||||
p1a_skp: int = 0
|
||||
p1a_fl: int = 0
|
||||
|
||||
# ============================================================
|
||||
# [临时取证打点] Phase1 早期扁平缓冲分配失败现场快照(定位后清理)。
|
||||
# 现场:class_names_buf/parent_names_buf 均成功,def_sha1s_buf 却返回 NULL;
|
||||
# 此时主池(1GiB)远未耗尽 → 非 OOM。本打点仅只读 mb 状态 + 打印,
|
||||
# 绝不改变任何分配行为与逻辑。三维度判定:
|
||||
# ① OOM:dump_stats 显示 used≈total、free≈0;
|
||||
# ② mb 损坏:usable 基址/大小荒谬、self_check != 0、max_order 异常;
|
||||
# ③ size/order 异常:本次请求 size 算出的 order > max_order。
|
||||
# 用 VLogger.info(非终止;VLogger.error 会 sys.exit(1) 掩盖后续打点)。
|
||||
# ============================================================
|
||||
if mb is not None:
|
||||
# 先做带环检测的 self_check:free list 被写坏成环时 dump_stats 的
|
||||
# free_bytes/free_count 无步数上限会死循环(打点自身卡死),故
|
||||
# self_check 返回 4(成环)时跳过 dump_stats。
|
||||
p1_sc: int = mb.self_check()
|
||||
if p1_sc != 4:
|
||||
mb.dump_stats("phase1-pre")
|
||||
else:
|
||||
VLogger.info("[取证] self_check=4(free list 成环),跳过 dump_stats 防死循环", "Phase1")
|
||||
p1_mo: int = mb.max_order
|
||||
if p1_mo < 0 or p1_mo > 32:
|
||||
p1_mo = 32 # 钳制:max_order 被写坏时防本打点自身越界读 free_lists
|
||||
p1_fl_head: uint64 = uint64(mb.free_lists[p1_mo])
|
||||
p1_mb_addr: uint64 = uint64(mb)
|
||||
p1_base_addr: uint64 = uint64(mb.base)
|
||||
p1_usable_addr: uint64 = uint64(mb.usable)
|
||||
p1_chkbase_addr: uint64 = uint64(mb.chk_base)
|
||||
VLogger.info(
|
||||
f"[取证] mb={p1_mb_addr} base={p1_base_addr} usable={p1_usable_addr} "
|
||||
f"usable_size={mb.usable_size} max_order={mb.max_order} self_check={p1_sc} "
|
||||
f"detection={mb.detection}", "Phase1")
|
||||
VLogger.info(
|
||||
f"[取证] chk_base={p1_chkbase_addr} chk_depth={mb.chk_depth} "
|
||||
f"chk_cap={mb.chk_cap} free_lists[clamp={p1_mo}]={p1_fl_head}",
|
||||
"Phase1")
|
||||
p1_sz_cn: sizet = sizet(Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
p1_sz_ds: sizet = sizet(Phase1.MAX_CLASSES * Phase1.SHA1_LEN)
|
||||
p1_sz_tp: sizet = sizet(4 * Phase1.MAX_FILE_DEPS)
|
||||
p1_sz_bx: sizet = sizet(4)
|
||||
p1_o_cn: int = mb._order_for_size(p1_sz_cn + 16)
|
||||
p1_o_ds: int = mb._order_for_size(p1_sz_ds + 16)
|
||||
p1_o_tp: int = mb._order_for_size(p1_sz_tp + 16)
|
||||
p1_o_bx: int = mb._order_for_size(p1_sz_bx + 16)
|
||||
p1_fl_cn: uint64 = uint64(mb.free_lists[p1_o_cn])
|
||||
p1_fl_ds: uint64 = uint64(mb.free_lists[p1_o_ds])
|
||||
VLogger.info(
|
||||
f"[取证] order(class_names {p1_sz_cn}B+16)={p1_o_cn} fl={p1_fl_cn} "
|
||||
f"order(def_sha1s {p1_sz_ds}B+16)={p1_o_ds} fl={p1_fl_ds} "
|
||||
f"order(topo {p1_sz_tp}B+16)={p1_o_tp} order(box {p1_sz_bx}B+16)={p1_o_bx} "
|
||||
f"(fl==0 只说明该阶空、仍可由更高阶拆分;若 alloc 失败而 dump_stats 的 free>0 才是元数据损坏铁证,"
|
||||
f"任一 order>max_order={mb.max_order} 则是 size 异常)",
|
||||
"Phase1")
|
||||
|
||||
# 预扫描类继承关系,构建拓扑顺序(用扁平字节数组,避免结构体 str 指针 NULL 崩溃)
|
||||
class_names_buf: bytes = mb.alloc(Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
parent_names_buf: bytes = mb.alloc(Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
@@ -451,42 +504,57 @@ def RunPhase1(mb: rowptr[memhub.MemBuddy], includes_dir: str, temp_dir: str,
|
||||
string.memset(generic_file_count_box, 0, 4)
|
||||
topo_count: int = 0
|
||||
|
||||
if class_names_buf is not None and parent_names_buf is not None and def_sha1s_buf is not None and topo_order is not None and topo_count_box is not None:
|
||||
string.memset(class_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
string.memset(parent_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
string.memset(def_sha1s_buf, 0, Phase1.MAX_CLASSES * Phase1.SHA1_LEN)
|
||||
string.memset(topo_order, 0, 4 * Phase1.MAX_FILE_DEPS)
|
||||
string.memset(topo_count_box, 0, 4)
|
||||
if generic_file_indices is not None:
|
||||
string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS)
|
||||
if generic_file_count_box is not None:
|
||||
string.memset(generic_file_count_box, 0, 4)
|
||||
# 三块扁平缓冲是 Phase1Scan._ScanClassInheritance 的契约前置缓冲:函数
|
||||
# 入口已对 NULL 做 fail-fast 检查(本处分配失败若静默跳过整段,将退化为
|
||||
# 字母序并掩盖 OOM 等内存故障)。故分配失败时逐块显式报错终止(VLogger.error
|
||||
# 内部 sys.exit(1)),绝不静默回退。
|
||||
# 注:topo_order/topo_count_box 仅供后续 Phase1Topo._TopoSortFiles 使用,
|
||||
# 不属 _ScanClassInheritance 契约,故不并入此处终止逻辑;其有效性由
|
||||
# _TopoSortFiles 入口自身校验(out_order/out_count 为 NULL 即返回 -1 并终止)。
|
||||
if class_names_buf is None:
|
||||
VLogger.error("类继承预扫描扁平缓冲分配失败:class_names_buf 为 NULL,终止编译", "Phase1")
|
||||
if parent_names_buf is None:
|
||||
VLogger.error("类继承预扫描扁平缓冲分配失败:parent_names_buf 为 NULL,终止编译", "Phase1")
|
||||
if def_sha1s_buf is None:
|
||||
VLogger.error("类继承预扫描扁平缓冲分配失败:def_sha1s_buf 为 NULL,终止编译", "Phase1")
|
||||
|
||||
class_count_scanned: int = Phase1Scan._ScanClassInheritance(
|
||||
string.memset(class_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
string.memset(parent_names_buf, 0, Phase1.MAX_CLASSES * Phase1.CLASS_NAME_LEN)
|
||||
string.memset(def_sha1s_buf, 0, Phase1.MAX_CLASSES * Phase1.SHA1_LEN)
|
||||
if topo_order is not None:
|
||||
string.memset(topo_order, 0, 4 * Phase1.MAX_FILE_DEPS)
|
||||
if topo_count_box is not None:
|
||||
string.memset(topo_count_box, 0, 4)
|
||||
if generic_file_indices is not None:
|
||||
string.memset(generic_file_indices, 0, 4 * Phase1.MAX_FILE_DEPS)
|
||||
if generic_file_count_box is not None:
|
||||
string.memset(generic_file_count_box, 0, 4)
|
||||
|
||||
class_count_scanned: int = Phase1Scan._ScanClassInheritance(
|
||||
mb, result, reachable_set, reachable_count,
|
||||
use_reachable, sha1_set, set_count,
|
||||
class_names_buf, parent_names_buf, def_sha1s_buf,
|
||||
generic_file_indices, generic_file_count_box)
|
||||
|
||||
if class_count_scanned > 0:
|
||||
td_len_ts_call: sizet = string.strlen(temp_dir)
|
||||
ret_topo: int = Phase1Topo._TopoSortFiles(
|
||||
mb, result, reachable_set, reachable_count,
|
||||
use_reachable, sha1_set, set_count,
|
||||
class_names_buf, parent_names_buf, def_sha1s_buf,
|
||||
generic_file_indices, generic_file_count_box)
|
||||
|
||||
if class_count_scanned > 0:
|
||||
td_len_ts_call: sizet = string.strlen(temp_dir)
|
||||
ret_topo: int = Phase1Topo._TopoSortFiles(
|
||||
mb, result, reachable_set, reachable_count,
|
||||
use_reachable, sha1_set, set_count,
|
||||
class_names_buf, parent_names_buf, def_sha1s_buf, class_count_scanned,
|
||||
topo_order, topo_count_box,
|
||||
temp_dir, td_len_ts_call)
|
||||
if ret_topo == 0:
|
||||
tc_ptr: t.CPtr = (int | t.CPtr)(t.CVoid(topo_count_box, t.CPtr))
|
||||
if tc_ptr is not None:
|
||||
topo_count = tc_ptr[0]
|
||||
VLogger.info(f"拓扑排序: {class_count_scanned} 个类, {topo_count} 个文件按依赖顺序处理", "Phase1")
|
||||
else:
|
||||
VLogger.error("拓扑排序失败(类继承依赖无法解析),终止编译", "Phase1")
|
||||
return 1
|
||||
class_names_buf, parent_names_buf, def_sha1s_buf, class_count_scanned,
|
||||
topo_order, topo_count_box,
|
||||
temp_dir, td_len_ts_call)
|
||||
if ret_topo == 0:
|
||||
tc_ptr: t.CPtr = (int | t.CPtr)(t.CVoid(topo_count_box, t.CPtr))
|
||||
if tc_ptr is not None:
|
||||
topo_count = tc_ptr[0]
|
||||
VLogger.info(f"拓扑排序: {class_count_scanned} 个类, {topo_count} 个文件按依赖顺序处理", "Phase1")
|
||||
else:
|
||||
VLogger.warning("类继承预扫描无结果,回退到字母序", "Phase1")
|
||||
topo_count = 0
|
||||
VLogger.error("拓扑排序失败(类继承依赖无法解析),终止编译", "Phase1")
|
||||
return 1
|
||||
else:
|
||||
VLogger.warning("类继承预扫描无结果,回退到字母序", "Phase1")
|
||||
topo_count = 0
|
||||
|
||||
# ============================================================
|
||||
# Phase 1a-pre-generic-all: mark1 前全量预注册 includes 泛型模板
|
||||
|
||||
@@ -76,8 +76,15 @@ def _ScanClassInheritance(mb: rowptr[memhub.MemBuddy],
|
||||
generic_file_indices: t.CPtr,
|
||||
generic_file_count_box: t.CPtr) -> int:
|
||||
"""预扫描 includes 文件,收集类继承关系"""
|
||||
if result is None or class_names_buf is None or parent_names_buf is None or def_sha1s_buf is None:
|
||||
if result is None:
|
||||
return -1
|
||||
# class_names_buf/parent_names_buf/def_sha1s_buf 由调用方 mb.alloc 分配
|
||||
# (Phase1Main 预扫描前),本函数将其地址直接作为 strcpy 的目的缓冲
|
||||
# (name_dst/parent_dst/sha1_dst)。分配失败返回 NULL 时目的指针为近零地址
|
||||
# → strcpy 写零页(ASan access-violation)。按 fail-fast 规则显式报错终止
|
||||
# (VLogger.error 内部 sys.exit(1)),不静默返回 -1 交由调用方宽容跳过。
|
||||
if class_names_buf is None or parent_names_buf is None or def_sha1s_buf is None:
|
||||
VLogger.error("类继承预扫描扁平缓冲分配失败(class_names_buf/parent_names_buf/def_sha1s_buf 为 NULL)", "Phase1")
|
||||
|
||||
entry_size: sizet = IncludesScanner.FileEntry.__sizeof__()
|
||||
class_count: int = 0
|
||||
|
||||
Reference in new issue
Block a user