fix(stubmerger): 依赖 worklist 去重,修复 64KB 溢出(app_deps 与 BFS 展开均无去重,公共模块重复累积导致溢出;三处逐模块词边界去重,溢出检查保留作防线)
This commit is contained in:
1 parent
b08a0aff48
commit
b68ae16639
2 files changed
+98
-24
No files matched your search
+31
-7
@@ -587,14 +587,38 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
# 收集 _imported_modules 到 app_deps_buf(供 Phase B+ 按需编译)。
|
||||
# 依赖在翻译早期已填充,即使 _deps_pending 也收集。
|
||||
if tr_a._imported_modules is not None and app_deps_buf is not None:
|
||||
# 逐模块去重拼接:多个 App 文件 import 同一模块(builtins/
|
||||
# _list/_dict/stdlib/t/c 等公共依赖)会让 app_deps 无去重
|
||||
# 膨胀到接近 64KB,_BuildReachableSha1Set 的初始 worklist
|
||||
# 即满 → BFS 展开必报"依赖 worklist 溢出"。
|
||||
im_len_a: t.CSizeT = string.strlen(tr_a._imported_modules)
|
||||
if im_len_a > 0 and app_deps_len + im_len_a + 1 < APP_DEPS_BUF_SIZE:
|
||||
if app_deps_len > 0:
|
||||
app_deps_buf[app_deps_len] = ' '
|
||||
app_deps_len = app_deps_len + 1
|
||||
string.strcpy(app_deps_buf + app_deps_len, tr_a._imported_modules)
|
||||
app_deps_len = app_deps_len + im_len_a
|
||||
app_deps_buf[app_deps_len] = '\0'
|
||||
im_pos_a: t.CSizeT = 0
|
||||
while im_pos_a < im_len_a:
|
||||
im_start_a: t.CSizeT = im_pos_a
|
||||
while im_pos_a < im_len_a and tr_a._imported_modules[im_pos_a] != ' ':
|
||||
im_pos_a += 1
|
||||
im_mod_len: t.CSizeT = im_pos_a - im_start_a
|
||||
if im_pos_a < im_len_a:
|
||||
im_pos_a += 1
|
||||
if im_mod_len == 0:
|
||||
continue
|
||||
im_mod_buf: bytes = stdlib.malloc(im_mod_len + 1)
|
||||
if im_mod_buf is None:
|
||||
continue
|
||||
string.strncpy(im_mod_buf, tr_a._imported_modules + im_start_a, im_mod_len)
|
||||
im_mod_buf[im_mod_len] = '\0'
|
||||
# 已在 app_deps 中则跳过(词边界精确匹配)
|
||||
if app_deps_len > 0 and HandlesImports.is_module_imported(app_deps_buf, im_mod_buf) != 0:
|
||||
stdlib.free(im_mod_buf)
|
||||
continue
|
||||
if app_deps_len + im_mod_len + 2 < APP_DEPS_BUF_SIZE:
|
||||
if app_deps_len > 0:
|
||||
app_deps_buf[app_deps_len] = ' '
|
||||
app_deps_len = app_deps_len + 1
|
||||
string.strcpy(app_deps_buf + app_deps_len, im_mod_buf)
|
||||
app_deps_len = app_deps_len + im_mod_len
|
||||
app_deps_buf[app_deps_len] = '\0'
|
||||
stdlib.free(im_mod_buf)
|
||||
if tr_a._deps_pending != 0:
|
||||
# 依赖模块 text.ll 未生成(同项目文件顺序),不写盘,下遍重试
|
||||
fb_dp: str = VLogger.fmt_buf()
|
||||
|
||||
@@ -538,13 +538,36 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
|
||||
tr._inject_auto_container_visibility(mb, tree)
|
||||
# 获取 _imported_modules
|
||||
if tr._imported_modules is not None:
|
||||
# 逐模块去重追加(同 app_deps 拼接,防 worklist 膨胀溢出)
|
||||
im_len: t.CSizeT = string.strlen(tr._imported_modules)
|
||||
if im_len > 0 and wl_len + im_len + 1 < REACH_WORKLIST_BUF:
|
||||
string.strcpy(worklist + wl_len, tr._imported_modules)
|
||||
wl_len += im_len
|
||||
worklist[wl_len] = ' '
|
||||
wl_len += 1
|
||||
worklist[wl_len] = '\0'
|
||||
im_pos: t.CSizeT = 0
|
||||
while im_pos < im_len:
|
||||
im_start: t.CSizeT = im_pos
|
||||
while im_pos < im_len and tr._imported_modules[im_pos] != ' ':
|
||||
im_pos += 1
|
||||
im_mod_len: t.CSizeT = im_pos - im_start
|
||||
if im_pos < im_len:
|
||||
im_pos += 1
|
||||
if im_mod_len == 0:
|
||||
continue
|
||||
im_buf: bytes = stdlib.malloc(im_mod_len + 1)
|
||||
if im_buf is None:
|
||||
continue
|
||||
string.strncpy(im_buf, tr._imported_modules + im_start, im_mod_len)
|
||||
im_buf[im_mod_len] = '\0'
|
||||
if wl_len > 0 and HandlesImports.is_module_imported(worklist, im_buf) != 0:
|
||||
stdlib.free(im_buf)
|
||||
continue
|
||||
if wl_len + im_mod_len + 2 < REACH_WORKLIST_BUF:
|
||||
if wl_len > 0:
|
||||
worklist[wl_len] = ' '
|
||||
wl_len += 1
|
||||
string.strcpy(worklist + wl_len, im_buf)
|
||||
wl_len += im_mod_len
|
||||
worklist[wl_len] = ' '
|
||||
wl_len += 1
|
||||
worklist[wl_len] = '\0'
|
||||
stdlib.free(im_buf)
|
||||
# 计算 App 源文件 SHA1,填充依赖到内存存储器
|
||||
# worklist 遍历时,LookupIncludesDeps 能找到 App 源文件的依赖
|
||||
if e_r.Sha1 is not None:
|
||||
@@ -662,17 +685,44 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str,
|
||||
if deps_str is not None:
|
||||
dl: t.CSizeT = string.strlen(deps_str)
|
||||
if dl > 0:
|
||||
if wl_len + dl + 2 < REACH_WORKLIST_BUF:
|
||||
if wl_len > 0 and worklist[wl_len - 1] != ' ':
|
||||
worklist[wl_len] = ' '
|
||||
wl_len = wl_len + 1
|
||||
string.strcpy(worklist + wl_len, deps_str)
|
||||
wl_len = wl_len + dl
|
||||
worklist[wl_len] = ' '
|
||||
wl_len = wl_len + 1
|
||||
worklist[wl_len] = '\0'
|
||||
else:
|
||||
VLogger.error("依赖 worklist 溢出", "StubMerger")
|
||||
# 逐模块追加 + 去重:worklist 初始已含全部 App 直接依赖,
|
||||
# deps_str 中的模块若已在 worklist/processed 不重复追加,
|
||||
# 否则 BFS 沿共享依赖(builtins/stdlib 等)反复累积到
|
||||
# 64KB 溢出("依赖 worklist 溢出"根因)。
|
||||
dpos: t.CSizeT = 0
|
||||
while dpos < dl:
|
||||
dstart: t.CSizeT = dpos
|
||||
while dpos < dl and deps_str[dpos] != ' ':
|
||||
dpos += 1
|
||||
dlen: t.CSizeT = dpos - dstart
|
||||
if dpos < dl:
|
||||
dpos += 1
|
||||
if dlen == 0:
|
||||
continue
|
||||
dmod: bytes = stdlib.malloc(dlen + 1)
|
||||
if dmod is None:
|
||||
continue
|
||||
string.strncpy(dmod, deps_str + dstart, dlen)
|
||||
dmod[dlen] = '\0'
|
||||
in_wl: int = 0
|
||||
if HandlesImports.is_module_imported(worklist, dmod) != 0:
|
||||
in_wl = 1
|
||||
if in_wl == 0 and processed is not None:
|
||||
if HandlesImports.is_module_imported(processed, dmod) != 0:
|
||||
in_wl = 1
|
||||
if in_wl == 0:
|
||||
if wl_len + dlen + 2 < REACH_WORKLIST_BUF:
|
||||
if wl_len > 0 and worklist[wl_len - 1] != ' ':
|
||||
worklist[wl_len] = ' '
|
||||
wl_len = wl_len + 1
|
||||
string.strcpy(worklist + wl_len, dmod)
|
||||
wl_len = wl_len + dlen
|
||||
worklist[wl_len] = ' '
|
||||
wl_len = wl_len + 1
|
||||
worklist[wl_len] = '\0'
|
||||
else:
|
||||
VLogger.error("依赖 worklist 溢出", "StubMerger")
|
||||
stdlib.free(dmod)
|
||||
# deps_str 为空字符串视为无依赖(合法情况,如叶子模块)
|
||||
else:
|
||||
# 依赖未在内存中找到
|
||||
|
||||
Reference in new issue
Block a user