From c35246f4267c06be0b58b8bfd4dfc2cc9644a775 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 5 Sep 2026 12:56:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(phase1):=20=E6=97=A7=205=20=E5=8F=82=20def?= =?UTF-8?q?=20=E5=89=8D=E8=A1=A5=E5=85=A8=E9=87=8F=20includes=20=E9=A2=84?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=EF=BC=881a-pre=EF=BC=89=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D'=E6=97=A0=E6=B3=95=E6=9E=84=E5=BB=BA=20SHA1=20?= =?UTF-8?q?=E6=98=A0=E5=B0=84'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 178ea40 重构把全量 includes 扫描/注册(PopulateSha1MapStore + 逐文件 import 依赖 PopulateIncludesDeps)从 Phase1Main 移除,依赖注册式 def 在 BFS 中自行登记。改用旧 5 参只读 def(调用点同步改回 5 参)后 store 无预注册 → _BuildIncludesSha1Map 返回 0 → '无法构建 SHA1 映射' 终止。 按 ab0f37e 1a-pre 模式补回:scan_includes 全量扫描 → PopulateSha1MapStore 登记 store → 逐文件 declare_only=2 解析 import 依赖(含 _inject_auto_container_visibility)→ PopulateIncludesDeps(文件级 mark/reset 防 OOM)。_BuildReachableResult 增加 reachable_set/count 过滤,result 只保留可达 includes 子集(1a/1b 只翻译可达文件)。 --- App/lib/Phase/Phase1/Phase1Main.vp | 118 ++++++++++++++++++++++++++++- App/lib/Phase/Phase2/__init__.vp | 6 +- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index 327fd2d..611f26d 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -244,8 +244,14 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int: # ScanResult 指针(stdlib 分配,调用方负责释放);失败返回 None # ============================================================ def _BuildReachableResult(mb: memhub.MemBuddy | t.CPtr, - includes_dir: str) -> IncludesScanner.ScanResult | t.CPtr: - """从 Sha1Store(仅可达 includes + App)构建可达 FileEntry 列表""" + includes_dir: str, + reachable_set: str = None, + reachable_count: int = 0) -> IncludesScanner.ScanResult | t.CPtr: + """从 Sha1Store(可达 includes + App)构建可达 FileEntry 列表 + + reachable_set/reachable_count 非空时按可达集合过滤:includes 预注册是 + 全量 store(PopulateSha1MapStore),1a/1b 只处理 reachable 子集。 + """ if mb is None: return None store_count: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) @@ -264,6 +270,10 @@ def _BuildReachableResult(mb: memhub.MemBuddy | t.CPtr, iidx: t.CSizeT = t.CSizeT(i) * StubMerger.MAX_INC_DIR_LEN if StubMerger._sha1_store_incdir[iidx] == '\0': continue + # 可达过滤(预注册为全量 store,result 只保留 reachable 子集) + if reachable_count > 0 and reachable_set is not None: + if StubMergerCollect._is_in_sha1_set(StubMerger._sha1_store_arr + sidx, reachable_set, reachable_count) == 0: + continue eaddr: t.CUInt64T = t.CUInt64T(result.Entries) + t.CUInt64T(result.Count) * entry_size entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(eaddr, t.CPtr)) if entry is None: @@ -361,6 +371,105 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 悬空 → 后续 tokenize 的 _kw_lookup strcmp 访问 0x4 崩溃(1.log ASan)。 ast._init_tables(mb) + # ============================================================ + # 旧 5 参 def 兼容预注册(补回 178ea40 重构时移除的 1a-pre) + # + # 旧 _BuildReachableSha1Set 只读全局存储器:BFS 前必须已有全量 + # includes 的 sha1→module 映射(PopulateSha1MapStore)与每文件的 + # import 依赖内存(PopulateIncludesDeps)。注册式新 def 是在 BFS 中 + # 自行登记,旧 def 没有该逻辑,故在 reachable 之前全量扫描注册。 + # ============================================================ + pp_t0: t.CUInt64T = w32.win32base.GetTickCount64() + pp_res: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir) + if pp_res is None: + VLogger.error("includes 预扫描失败(scan_includes 返回 None),终止编译", "Phase1") + return 1 + pp_es: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() + pp_store_count: int = StubMergerStore.PopulateSha1MapStore(pp_res) + if pp_store_count <= 0: + VLogger.error(f"includes 预注册失败(PopulateSha1MapStore={pp_store_count}),终止编译", "Phase1") + return 1 + pp_fail: int = 0 + pp_ok: int = 0 + for pp_i in range(pp_res.Count): + pp_mark: t.CSizeT = mb.mark() + pp_ea: t.CUInt64T = t.CUInt64T(pp_res.Entries) + t.CUInt64T(pp_i) * pp_es + pp_ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(pp_ea, t.CPtr)) + if pp_ent is None or pp_ent.Sha1 is None or pp_ent.Path is None: + pp_fail += 1 + mb.reset_to(pp_mark) + continue + pp_sha1: str = pp_ent.Sha1 + pp_f: fileio.File | t.CPtr = fileio.File(pp_ent.Path, fileio.MODE.R) + if pp_f.closed: + pp_fail += 1 + mb.reset_to(pp_mark) + continue + pp_buf: bytes = stdlib.malloc(Phase1.SRC_BUF_SIZE) + if pp_buf is None: + pp_f.close() + pp_fail += 1 + mb.reset_to(pp_mark) + continue + pp_br: LONG = pp_f.read_all(pp_buf, Phase1.SRC_BUF_SIZE) + pp_f.close() + if pp_br <= 0: + stdlib.free(pp_buf) + pp_fail += 1 + mb.reset_to(pp_mark) + continue + if pp_br < Phase1.SRC_BUF_SIZE: + pp_buf[pp_br] = 0 + else: + pp_buf[Phase1.SRC_BUF_SIZE - 1] = 0 + pp_lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) + pp_tree: ast.AST | t.CPtr = None + if pp_lx is not None: + ast._lexer_init(pp_lx, pp_buf, mb) + pp_tok: ast.Token | t.CPtr = ast.tokenize(pp_lx) + pp_tree = ast.parse_tokens(mb, pp_tok) + if pp_tree is None: + stdlib.free(pp_buf) + pp_fail += 1 + VLogger.error(f"includes 预注册解析失败: {pp_ent.Path}", "Phase1") + mb.reset_to(pp_mark) + continue + pp_tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() + if pp_tr is None: + stdlib.free(pp_buf) + pp_fail += 1 + mb.reset_to(pp_mark) + continue + pp_tr.ModuleSha1 = pp_sha1 + pp_tr._declare_only = 2 + pp_tr.CurrentPackage = GenApi.compute_package_from_relpath(mb, pp_ent.RelPath) + GenApi.set_current_file_type(pp_ent.Path) + GenApi.set_current_file_imports(pp_ent.Path) + GenApi.set_current_module_sha1(pp_sha1) + GenApi.clear_cdefine_constants() + GenApi.clear_ctypedefs() + GenApi.reset_visible_structs(mb, 0) + pp_rc: int = pp_tr.translate(pp_tree) + if pp_rc == 0: + pp_tr._inject_auto_container_visibility(mb, pp_tree) + if pp_tr._imported_modules is not None: + StubMergerStore.PopulateIncludesDeps(pp_sha1, pp_tr._imported_modules) + pp_ok += 1 + else: + pp_fail += 1 + VLogger.error(f"includes 预注册翻译失败: {pp_ent.Path}", "Phase1") + if pp_tr._global_names is not None: + stdlib.free(pp_tr._global_names) + if pp_tr._nonlocal_names is not None: + stdlib.free(pp_tr._nonlocal_names) + stdlib.free(pp_buf) + mb.reset_to(pp_mark) + pp_t1: t.CUInt64T = w32.win32base.GetTickCount64() + VLogger.info(f"includes 预注册: {pp_ok} 个(失败 {pp_fail},{pp_t1 - pp_t0} ms)", "Phase1") + if pp_fail > 0: + VLogger.error(f"includes 预注册有 {pp_fail} 个失败,终止编译", "Phase1") + return 1 + # 依赖图按需扫描(App 优先模型): # 1) 先扫 App 源文件(Config.SourceDir)的 import 依赖 → 初始队列 # 2) BFS 沿队列按文件系统解析 includes 文件,只对可达 includes @@ -376,7 +485,7 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, if reachable_set is not None: string.memset(reachable_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) reachable_count = StubMergerBuild._BuildReachableSha1Set( - mb, Config.SourceDir, temp_dir, reachable_set, None, includes_dir) + mb, Config.SourceDir, temp_dir, reachable_set, None) if reachable_count < 0: VLogger.error("可达集合构建失败(依赖图扫描失败),终止编译", "Phase1") return 1 @@ -398,7 +507,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, # 从 Sha1Store(仅可达 includes + App)构造可达 FileEntry 列表: # 后续 1a/1b-pre/1b 直接遍历 result(incdir 非空条目=includes), # use_reachable 过滤幂等保留(result 即可达子集) - result: IncludesScanner.ScanResult | t.CPtr = _BuildReachableResult(mb, includes_dir) + result: IncludesScanner.ScanResult | t.CPtr = _BuildReachableResult( + mb, includes_dir, reachable_set, reachable_count) if result is None: VLogger.error("可达 FileEntry 列表构建失败,终止编译", "Phase1") return 1 diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 16b770e..c842d9d 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -763,7 +763,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, do_phase1: int, do_phase2: int, log: VLogger.Logger | t.CPtr, args: argparse.ParsedArgs | t.CPtr, - linker_static_libs: str = None, + linker_static_libs: str = None, linker_dynamic_libs: str = None) -> int: """多文件项目编译 @@ -837,7 +837,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, else: string.memset(rs_05, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) rc_05: int = StubMergerBuild._BuildReachableSha1Set( - mb, source_dir, temp_dir, rs_05, None, includes_dir) + mb, source_dir, temp_dir, rs_05, None) if rc_05 < 0: VLogger.error("依赖图扫描失败,无法填充 Sha1Store", "project") elif rc_05 > 0: @@ -1615,7 +1615,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, if reachable_set is not None: string.memset(reachable_set, 0, REACHABLE_SET_SIZE) reachable_count = StubMergerBuild._BuildReachableSha1Set( - mb, source_dir, temp_dir, reachable_set, app_deps_buf, includes_dir) + mb, source_dir, temp_dir, reachable_set, app_deps_buf) VLogger.info(f"可达 includes SHA1: {reachable_count} 个", "PhaseB+") # fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止 if reachable_count < 0: