diff --git a/App/lib/Stub/StubMerger/StubMergerIR.vp b/App/lib/Stub/StubMerger/StubMergerIR.vp index e6dfeaa..d18bf5c 100644 --- a/App/lib/Stub/StubMerger/StubMergerIR.vp +++ b/App/lib/Stub/StubMerger/StubMergerIR.vp @@ -364,7 +364,9 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str, # 第一遍:精确匹配 for i in range(count): idx: sizet = sizet(i) * 64 - if string.strcmp(mod_arr + idx, mod_name) == 0: + # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp + # (热点:本函数全表逐条 strcmp 查名)。 + if mod_arr[idx] == mod_name[0] and string.strcmp(mod_arr + idx, mod_name) == 0: sidx: sizet = sizet(i) * 17 return sha1_arr + sidx # 第二遍:包名回退("ast" → "ast.__init__") @@ -374,7 +376,7 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str, viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name) for i in range(count): idx2: sizet = sizet(i) * 64 - if string.strcmp(mod_arr + idx2, init_buf) == 0: + if mod_arr[idx2] == init_buf[0] and string.strcmp(mod_arr + idx2, init_buf) == 0: sidx2: sizet = sizet(i) * 17 stdlib.free(init_buf) return sha1_arr + sidx2 diff --git a/App/lib/core/Gen/Call/CallGenBase.vp b/App/lib/core/Gen/Call/CallGenBase.vp index 4df3eba..41801fb 100644 --- a/App/lib/core/Gen/Call/CallGenBase.vp +++ b/App/lib/core/Gen/Call/CallGenBase.vp @@ -645,7 +645,10 @@ class CallGenBase: stdio.printf("[CALLGEN] 链表异常: module funcs(call_name=%s,遍历超限,终止)\n", call_name) stdlib.exit(1) if existing.Name is not None: - if string.strcmp(existing.Name, call_name) == 0: + # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp + # (热点:本函数对模块函数链逐节点命名比对)。 + if existing.Name[0] == call_name[0] \ + and string.strcmp(existing.Name, call_name) == 0: # 已存在:仅当是 declare 且参数数量不足时追加缺失参数 if existing.IsDeclared == 1: # 变长函数(*args,IsVarArg=1)不追加参数:多余实参由 diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index cf549d0..8e729ca 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -1498,7 +1498,8 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): entry_addr: uint64 = uint64(funcs) + i * entry_size entry: GenTypes.FuncEntry | t.CPtr = (GenTypes.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) if entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: + # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp + if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: return entry return None @@ -1524,7 +1525,9 @@ class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): entry: GenTypes.FuncEntry | t.CPtr = (GenTypes.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) if entry is None or entry.Name is None: continue - if string.strcmp(entry.Name, name) != 0: + # 快速路径:strcmp 判等要求首字符相等,首字符不同者跳过 strcmp + # (热点:本函数对函数表逐条按裸名 + 定义模块 SHA1 比对)。 + if entry.Name[0] != name[0] or string.strcmp(entry.Name, name) != 0: continue if owner_sha1 is None: return entry diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 32eb114..e8c9880 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -791,11 +791,22 @@ class StructGenMixin: fi: int = self._struct_name_idx_find(name) if fi >= 0: return self._get_struct_entry(fi) - for i in range(self.StructCount): - entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry + # 名索引可信(Built==Count | 索引存在 | 查询名非空)时,索引未命中即 + # "确无同名条目":条目在注册时即命名并同步入索引,之后名至多被中和为 "" + # (ClassGenDef/ClassGenEnum 置 Name[0]=0),故任何非空查询名的命中项必在 + # 索引探测链上 ⇒ 可跳过下方 O(n) 精确扫描(热点:本扫描占 find_struct 的 + # 全部 strcmp)。索引不可信 / 无索引 / 空名查询时仍回退原线性扫描 + # (正确性保证,非兜底)。 + name_idx_trusted: int = 0 + if self.StructNameIdx is not None and self.StructIdxCap > 0 \ + and self.StructIdxBuilt == self.StructCount: + name_idx_trusted = 1 + if name_idx_trusted == 0 or name[0] == '\0': + for i in range(self.StructCount): + entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i) + if entry is not None and entry.Name is not None: + if string.strcmp(entry.Name, name) == 0: + return entry # 模块限定名(module.Class):模块可解析时按模块归属精确匹配, # 防止裸名回退抓跨模块同名类。模块未命中时若裸名类唯一(无冲突) # 仍回退,避免误杀未登记模块的既有解析。 diff --git a/App/lib/core/Gen/Type/TypeGenBase.vp b/App/lib/core/Gen/Type/TypeGenBase.vp index 7a924b5..20bbdb4 100644 --- a/App/lib/core/Gen/Type/TypeGenBase.vp +++ b/App/lib/core/Gen/Type/TypeGenBase.vp @@ -79,6 +79,13 @@ class TypeGenBase: CTypedefNames: list[str] | t.CPtr CTypedefTypeStrs: list[str] | t.CPtr CTypedefFound: int + # CTypedef 名 → 槽下标 索引(开放寻址 | 线性探测;槽存 index+1,0=空槽)。 + # 与 CTypedefNames 同池分配、同 clear_ctypedefs 复位;CTypedefNames 只追加 + # 不重排(同名注册原地更新类型串)⇒ 存槽下标稳定;Built == len(CTypedefNames) + # 才可信,不可信/未命中一律回退线性扫描(正确性保证)。 + CTypedefNameIdx: sizet | t.CPtr + CTypedefNameIdxCap: int + CTypedefNameIdxBuilt: int CTypedefResolveDepth: int CTypedefVisiting: list[str] | t.CPtr # builtins 源扫描标记:注解解析"最后匹配"兜底(_lookup_builtins_typedef) @@ -151,6 +158,9 @@ class TypeGenBase: self.CTypedefNames = None self.CTypedefTypeStrs = None self.CTypedefFound = 0 + self.CTypedefNameIdx = None + self.CTypedefNameIdxCap = 0 + self.CTypedefNameIdxBuilt = -1 self.CTypedefResolveDepth = 0 self.CTypedefVisiting = None self.BuiltinsTypedefScanned = 0 diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index 96b7469..c079c91 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -16,6 +16,33 @@ import lib.core.CompilerFactory as CompilerFactory import lib.core.Gen.Type.TypeGenBase as TypeGenBase import lib.core.Gen.Type.TypeSpec as TSpec +# ============================================================ +# CTypedef 名索引(名 → 槽下标,开放寻址 | 线性探测) +# +# 槽数 = 4096(2 的幂;负载 < 0.5 上限 2048 条,超限标记不可信回退线性扫描)。 +# 槽存槽下标 + 1(0=空槽)。CTypedefNames 只追加不重排(同名注册原地更新类型串) +# ⇒ 槽下标稳定;Built == len(CTypedefNames) 才可信。 +# ============================================================ +CTYPEDEF_IDX_CAP: t.CDefine = 4096 +# 索引哈希常量(32 位 FNV-1a,与 StructGenMixin 范式一致) +CTYPEDEF_IDX_FNV_OFFSET: t.CDefine = 2166136261 +CTYPEDEF_IDX_FNV_PRIME: t.CDefine = 16777619 +CTYPEDEF_IDX_FNV_MASK: t.CDefine = 4294967295 + + +def _ctypedef_idx_hash(name: str) -> uint64: + """CTypedef 名 → 64 位哈希(32 位 FNV-1a,逐字节到 NUL 结束)""" + h: uint64 = uint64(CTYPEDEF_IDX_FNV_OFFSET) + if name is None: + return h + i: sizet = 0 + while name[i] != '\0': + h = (h ^ uint64(int(name[i]))) * uint64(CTYPEDEF_IDX_FNV_PRIME) + h = h & uint64(CTYPEDEF_IDX_FNV_MASK) + i += 1 + return h + + # ============================================================ # TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr) # @@ -27,6 +54,74 @@ import lib.core.Gen.Type.TypeSpec as TSpec class TypeGenCType(TypeGenBase.TypeGenBase): """CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)""" + # ============================================================ + # CTypedef 名索引(开放寻址;槽存 index+1,0=空槽) + # ============================================================ + def _ctypedef_idx_slot(self, si: sizet) -> sizet | t.CPtr: + """取索引第 si 个槽(8 字节,存槽下标+1;0=空槽)""" + return (sizet | t.CPtr)(t.CVoid(uint64(self.CTypedefNameIdx) + uint64(si) * 8, t.CPtr)) + + def _ctypedef_idx_init(self, pool: rowptr[memhub.MemBuddy]) -> None: + """创建/清零名索引(与 CTypedefNames 同池);失败则标记不可信""" + idx: sizet | t.CPtr = pool.alloc(sizet(CTYPEDEF_IDX_CAP) * 8) + if idx is None: + self.CTypedefNameIdx = None + self.CTypedefNameIdxCap = 0 + self.CTypedefNameIdxBuilt = -1 + return + string.memset(idx, 0, sizet(CTYPEDEF_IDX_CAP) * 8) + self.CTypedefNameIdx = idx + self.CTypedefNameIdxCap = CTYPEDEF_IDX_CAP + self.CTypedefNameIdxBuilt = 0 + + def _ctypedef_idx_find(self, name: str) -> int: + """在名索引中探测 name,返回命中槽下标(>=0);未命中/不可用返回 -1""" + if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: + return -1 + if self.CTypedefNameIdxBuilt != int(len(self.CTypedefNames)): + return -1 + h: uint64 = _ctypedef_idx_hash(name) + mask: sizet = sizet(self.CTypedefNameIdxCap - 1) + si: sizet = sizet(h) & mask + i: int = 0 + while i < self.CTypedefNameIdxCap: + slot: sizet | t.CPtr = self._ctypedef_idx_slot(si) + sv: sizet = slot[0] + if sv == 0: + return -1 + se: int = int(sv) - 1 + nm: str = self.CTypedefNames.get(sizet(se)) + if nm is not None and string.strcmp(nm, name) == 0: + return se + si = (si + 1) & mask + i += 1 + return -1 + + def _ctypedef_idx_insert(self, slot_index: int, name: str) -> int: + """把 (name → slot_index) 记入索引;0=成功 / 1=失败""" + if self.CTypedefNameIdx is None or self.CTypedefNameIdxCap <= 0 or name is None: + return 1 + h: uint64 = _ctypedef_idx_hash(name) + mask: sizet = sizet(self.CTypedefNameIdxCap - 1) + si: sizet = sizet(h) & mask + i: int = 0 + while i < self.CTypedefNameIdxCap: + slot: sizet | t.CPtr = self._ctypedef_idx_slot(si) + if slot[0] == 0: + slot[0] = sizet(slot_index + 1) + return 0 + si = (si + 1) & mask + i += 1 + return 1 + + def _ctypedef_idx_sync_append(self, name: str) -> None: + """CTypedefNames.append 后同步索引(槽下标 = len-1);不可信则保持不可信""" + n: int = int(len(self.CTypedefNames)) + if self.CTypedefNameIdxBuilt == n - 1 and self._ctypedef_idx_insert(n - 1, name) == 0: + self.CTypedefNameIdxBuilt = n + else: + self.CTypedefNameIdxBuilt = -1 + def register_ctypedef(self, pool: rowptr[memhub.MemBuddy], name: str, type_str: str) -> None: """注册 CTypedef 到本地表 @@ -60,6 +155,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): if self.CTypedefNames is None: self.CTypedefNames = list[str](pool, 64) self.CTypedefTypeStrs = list[str](pool, 64) + # 名索引随表创建(同池;分配失败则标记不可信,查找回退线性扫描) + self._ctypedef_idx_init(pool) # 去重:若已存在同名 CTypedef,更新其类型字符串 if self.CTypedefNames is not None: exist_n: sizet = len(self.CTypedefNames) @@ -72,6 +169,8 @@ class TypeGenCType(TypeGenBase.TypeGenBase): return self.CTypedefNames.append(name_copy) self.CTypedefTypeStrs.append(type_copy) + # 追加后同步名索引(槽下标 = 追加前 len = 新 len-1) + self._ctypedef_idx_sync_append(name_copy) def store_builtins_diag(self, which: int, text: str) -> str: """把 builtins 诊断串复制进自有缓冲并返回该缓冲(which: 0=Name, 1=Result) @@ -120,6 +219,17 @@ class TypeGenCType(TypeGenBase.TypeGenBase): return None n: sizet = len(self.CTypedefNames) i: sizet + # 名索引快速路径:可信(Built==n)时直接定位唯一候选槽下标。CTypedef 表 + # 注册时按名去重(register_ctypedef 已存在则原地更新类型串)⇒ 名唯一, + # 索引未命中 ⇒ 确实不存在,直接返回;索引不可用/不可信 → 回退原全表扫描。 + if self.CTypedefNameIdxBuilt == int(n) \ + and self.CTypedefNameIdx is not None and self.CTypedefNameIdxCap > 0: + ti: int = self._ctypedef_idx_find(name) + if ti < 0: + return None + ts_hit: str = self.CTypedefTypeStrs.get(sizet(ti)) + self.CTypedefFound = 1 + return ts_hit for i in range(n): nm: str = self.CTypedefNames.get(i) if nm is not None and string.strcmp(nm, name) == 0: @@ -284,6 +394,10 @@ class TypeGenCType(TypeGenBase.TypeGenBase): """清空 CTypedef 表(模块切换时调用)""" self.CTypedefNames = None self.CTypedefTypeStrs = None + # 名索引随表复位(下次 register 重建);不同步会使 Built 与空表错配 + self.CTypedefNameIdx = None + self.CTypedefNameIdxCap = 0 + self.CTypedefNameIdxBuilt = -1 self.CTypedefResolveDepth = 0 self.CTypedefVisiting = None # builtins 源扫描标记随表清空复位:每文件最多读一次 includes/builtins.vp diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 48ce15f..7b0284b 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -75,7 +75,8 @@ class VarGenMixin: entry_addr: uint64 = uint64(vars_ptr) + i * entry_size entry: GenTypes.VarEntry | t.CPtr = (GenTypes.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) if entry.Name is not None and entry.Used != 0: - if string.strcmp(entry.Name, name) == 0: + # 快速路径:strcmp 判等蕴含首字符相等,首字符不同者跳过 strcmp + if entry.Name[0] == name[0] and string.strcmp(entry.Name, name) == 0: return entry.Alloca return None