From 2ef6a55eadcd81f2ede4e4714657724dc6022af1 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 14 Aug 2026 04:13:59 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Phase1=20=E4=B8=89=E4=B8=AA=E6=97=A0=20r?= =?UTF-8?q?eset=20=E7=9A=84=E5=85=A8=E9=87=8F=20parse=20=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E6=94=B9=E6=AF=8F=E6=96=87=E4=BB=B6=E5=9B=9E=E6=94=B6=EF=BC=8C?= =?UTF-8?q?=E8=A7=A3=20mark1=20=E5=89=8D=20OOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NewAstTest 仍 1GB 主池耗尽:Phase1 1a 主循环已 reset,但此前还有 三处对全部 includes 全量 parse AST 且驻留到 mark1 的循环(可达 includes 数量多时 AST 累积超 1GB): 1. _ScanClassInheritance(类继承预扫描):每文件收集类名/父类/SHA1 到扁平数组后 reset_to(文件级 mark) 回收 AST; 2. Phase 1a-pre import 依赖扫描:deps 写盘 + PopulateIncludesDeps (内部 stdlib 深拷贝)后 reset_to(文件级 mark); 3. 删除冗余的 Phase 1a-pre-generic(主 pool 全量 parse 可达泛型文件、 无 reset)——已被 _PreRegisterAllGenericTemplates(文本扫描筛选 + perm_pool 注册,全覆盖)替代。 注:reset 只回收各文件的 AST/lexer/token/IR 等瞬时数据;注册表数据 (StructTable/Fields/Name/ModuleSha1/struct_ty 深拷贝/枚举/Renum/泛型 模板)已在前一轮迁入 perm_pool,不受 reset 影响。 --- App/lib/core/Phase1.vp | 105 ++++++++--------------------------------- 1 file changed, 19 insertions(+), 86 deletions(-) diff --git a/App/lib/core/Phase1.vp b/App/lib/core/Phase1.vp index 2fc31a2..2f6957a 100644 --- a/App/lib/core/Phase1.vp +++ b/App/lib/core/Phase1.vp @@ -85,6 +85,11 @@ def _ScanClassInheritance(mb: memhub.MemBuddy | t.CPtr, class_count: int = 0 for i in range(result.Count): + # 文件级 mark:收集完类继承信息后立即回收本文件 AST(可达 includes + # 全量 parse 的 AST 若驻留到 mark1 → 1GB 主池耗尽 OOM 根因; + # class_names_buf/parent_names_buf/def_sha1s_buf 在调用前分配, + # 位于本 mark 之前,reset 不影响;generic_file_indices 同理) + scan_mark: t.CSizeT = mb.mark() entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) if entry is None or entry.Sha1 is None: @@ -199,6 +204,8 @@ def _ScanClassInheritance(mb: memhub.MemBuddy | t.CPtr, class_count += 1 stdlib.free(src_buf) + # 回收本文件 AST/lexer/token(类名/父类/SHA1 已拷入扁平数组) + mb.reset_to(scan_mark) return class_count @@ -581,8 +588,12 @@ def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr, file_count: int = 0 # sha1→file_index 映射(简单线性查找,文件数不多) for i in range(result.Count): - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) + # 文件级 mark:import 依赖收集完(deps 写盘 + PopulateIncludesDeps + # 内部 stdlib 深拷贝)后立即回收本文件 AST——98 includes 全量 parse + # 的 AST 若驻留到 mark1 → 1GB 主池耗尽 OOM 根因之一 + scan_mark_a: t.CSizeT = mb.mark() + entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size + entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr)) if entry is None or entry.Sha1 is None: continue @@ -971,6 +982,10 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, p1a_failed: int = 0 for i in range(result.Count): + # 文件级 mark:import 依赖收集完(deps 写盘 + PopulateIncludesDeps + # 内部 stdlib 深拷贝)后立即回收本文件 AST——98 includes 全量 parse + # 的 AST 若驻留到 mark1 → 1GB 主池耗尽 OOM 根因之一 + scan_mark_a: t.CSizeT = mb.mark() entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr)) if entry_a is None: @@ -1095,6 +1110,8 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, stdlib.free(tr_a._nonlocal_names) stdlib.free(src_buf_a) + # 回收本文件 AST/lexer/token(deps 已写盘、依赖存储器已深拷贝) + mb.reset_to(scan_mark_a) if p1a_failed > 0: fb_p1apre: str = VLogger.fmt_buf() @@ -1206,90 +1223,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, VLogger.warning("类继承预扫描无结果,回退到字母序", "Phase1") topo_count = 0 - # ============================================================ - # Phase 1a-pre-generic: 预注册所有泛型类模板 - # - # 在 Phase 1a(struct 注册)之前执行,确保所有泛型类模板 - #(如 GSListNode[T]、GSList[T])已注册。这样当其他文件的 - # 结构体字段使用 GSListNode[Value] 等特化类型时,模板能被找到。 - # ============================================================ - generic_file_count: int = 0 - if generic_file_count_box is not None: - gfc_box_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(generic_file_count_box, t.CPtr)) - if gfc_box_ptr is not None: - generic_file_count = gfc_box_ptr[0] - - if generic_file_count > 0 and generic_file_indices is not None: - fb_gpre: str = VLogger.fmt_buf() - if fb_gpre is not None: - viperlib.snprintf(fb_gpre, 1024, "预注册 %d 个泛型类模板文件", generic_file_count) - VLogger.info(fb_gpre, "Phase1") - - for gi in range(generic_file_count): - gi_addr_p: t.CUInt64T = t.CUInt64T(generic_file_indices) + gi * 4 - gi_ptr_p: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(gi_addr_p, t.CPtr)) - if gi_ptr_p is None: - continue - file_idx_gen: int = gi_ptr_p[0] - - gen_entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + file_idx_gen * entry_size - gen_entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(gen_entry_addr, t.CPtr)) - if gen_entry is None or gen_entry.Sha1 is None: - continue - - gen_path: str = gen_entry.Path - gen_f: fileio.File | t.CPtr = fileio.File(gen_path, fileio.MODE.R) - if gen_f.closed: - continue - - gen_src: bytes = stdlib.malloc(SRC_BUF_SIZE) - if gen_src is None: - gen_f.close() - continue - - gen_br: LONG = gen_f.read_all(gen_src, SRC_BUF_SIZE) - gen_f.close() - if gen_br <= 0: - stdlib.free(gen_src) - continue - if gen_br < SRC_BUF_SIZE: - gen_src[gen_br] = 0 - else: - gen_src[SRC_BUF_SIZE - 1] = 0 - - gen_lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if gen_lx is None: - stdlib.free(gen_src) - continue - ast._lexer_init(gen_lx, gen_src, mb) - gen_tokens: ast.Token | t.CPtr = ast.tokenize(gen_lx) - gen_tree: ast.AST | t.CPtr = ast.parse_tokens(mb, gen_tokens) - if gen_tree is None: - stdlib.free(gen_src) - continue - - gen_tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if gen_tr is None: - stdlib.free(gen_src) - continue - gen_tr.ModuleSha1 = gen_entry.Sha1 - gen_tr._declare_only = 1 - gen_tr.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, gen_entry.RelPath) - HandlesType.set_current_file(gen_path) - HandlesImports.set_current_file(gen_path) - HandlesType.set_current_module_sha1(gen_entry.Sha1) - HandlesType.clear_cdefine_constants() - HandlesType.clear_ctypedefs() - HandlesStruct.reset_visible_structs(mb, 0) - - gen_tr.translate(gen_tree) - - if gen_tr._global_names is not None: - stdlib.free(gen_tr._global_names) - if gen_tr._nonlocal_names is not None: - stdlib.free(gen_tr._nonlocal_names) - stdlib.free(gen_src) - # ============================================================ # Phase 1a-pre-generic-all: mark1 前全量预注册 includes 泛型模板 #