From b68ae16639ff1bcb8b31af69ac175246e0ea8527 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 20 Aug 2026 03:11:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(stubmerger):=20=E4=BE=9D=E8=B5=96=20worklis?= =?UTF-8?q?t=20=E5=8E=BB=E9=87=8D=EF=BC=8C=E4=BF=AE=E5=A4=8D=2064KB=20?= =?UTF-8?q?=E6=BA=A2=E5=87=BA=EF=BC=88app=5Fdeps=20=E4=B8=8E=20BFS=20?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E5=9D=87=E6=97=A0=E5=8E=BB=E9=87=8D=EF=BC=8C?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E6=A8=A1=E5=9D=97=E9=87=8D=E5=A4=8D=E7=B4=AF?= =?UTF-8?q?=E7=A7=AF=E5=AF=BC=E8=87=B4=E6=BA=A2=E5=87=BA=EF=BC=9B=E4=B8=89?= =?UTF-8?q?=E5=A4=84=E9=80=90=E6=A8=A1=E5=9D=97=E8=AF=8D=E8=BE=B9=E7=95=8C?= =?UTF-8?q?=E5=8E=BB=E9=87=8D=EF=BC=8C=E6=BA=A2=E5=87=BA=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E4=BD=9C=E9=98=B2=E7=BA=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Phase2.vp | 38 ++++++++++++--- App/lib/core/StubMergerBuild.vp | 84 ++++++++++++++++++++++++++------- 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/App/lib/core/Phase2.vp b/App/lib/core/Phase2.vp index b9a67f3..4bbed38 100644 --- a/App/lib/core/Phase2.vp +++ b/App/lib/core/Phase2.vp @@ -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() diff --git a/App/lib/core/StubMergerBuild.vp b/App/lib/core/StubMergerBuild.vp index 264bbd1..3610544 100644 --- a/App/lib/core/StubMergerBuild.vp +++ b/App/lib/core/StubMergerBuild.vp @@ -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: # 依赖未在内存中找到