fix: Phase1 三个无 reset 的全量 parse 循环改每文件回收,解 mark1 前 OOM
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 影响。
This commit is contained in:
1 parent
8d5dbeab89
commit
2ef6a55ead
1 file changed
+19
-86
+19
-86
@@ -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 泛型模板
|
||||
#
|
||||
|
||||
Reference in new issue
Block a user