perf(全仓库/正则): 字面量正则全部改模块级预编译常量(15 文件 / 115 个调用点)
背景(prof 基线 PROF/20260930_224857,主进程 433.69s):正则这一族合计 ≈45s —— `re.match`(未预编译入口)被调 1970 万次 / 自身 10.70s、它内部 `Pattern.match` 占 8.06s, `re._compile`(缓存查找)1975 万次 / 7.19s,`re._make`(真正编译)274 万次 / 7.62s (说明 re 的 512 条缓存已被打穿,每 7 次调用就有 1 次重新编译)。 每次 `re.match(字面量, s)` 都要做"模式串哈希 → 缓存查找";预编译后这层全省掉。 改动:把 15 个文件里 97 处"字面量当模式"的 `re.match/search/sub/subn/fullmatch/ findall/finditer/split(...)` 提升为模块级 `_RE_*: re.Pattern[str] = re.compile(...)`, 共 115 个调用点(含同字面量跨处共用)。模式串与 flags 一字未改(flags 从调用处 搬进 re.compile,含原先以**位置参数**传入的 flags)。4 处拼接型动态模式按设计不动 (FuncGen 2 处、HandlesImports 2 处)。 核验(不靠肉眼):写了 AST 指纹对拍脚本,对每个文件取 HEAD 版与新工作区版,把 "旧 re.<m>(字面量, 其余实参, 关键字) + flags" 与 "新 _RE_X.<m>(实参, 关键字) + 常量 (模式, flags)" 做多重集比对 —— 15 个文件、115 个调用点全部逐一等价(0 失败), 另查无重名常量、无遗留字面量调用、GetDiagnostics 全空。 对拍过程中查出一处子代理抄写错误:`_RE_GLOBAL_DSOLOCAL_MULTILINE` 丢了行首锚 `^` (原文注释明确"使用 ^ + MULTILINE 避免匹配字符串常量内容中的 define/declare"),已修正。 同轮经查证后**未做改动**的两项(避免把假热点当真事修): - VLogger 的 `re.sub` 6.43s:profile 当时的 VLogger 版本里根本没有 `import re` (`git show 3658ab06:lib/core/VLogger.py` 已确认),属 C 帧错挂,不做。 - tokenize 274 万次:那是 `_generate_tokens_from_c_tokenizer` 的 **token 产出次数** (≈350 个整文件的词法量),SymbolUtils 的 4 个 tokenize 调用点 nc 仅数百,且已有 `_EXPAND_CACHE` 去重;再加一层 token 缓存无收益,不做。
This commit is contained in:
1 parent
4641777db1
commit
b18d57fa38
15 files changed
+318
-96
No files matched your search
@@ -11,9 +11,14 @@ from lib.includes.t import CTypeRegistry
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode,
|
||||
IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr,
|
||||
EnumClassIntWidth, ClassHasFuncLevelCVTable)
|
||||
|
||||
|
||||
EnumClassIntWidth, ClassHasFuncLevelCVTable)
|
||||
|
||||
# 泛型特化(`_SubstituteTypeArgs`)把 `%"SHA1.T"` / `%"SHA1.T"*` 替换为 i8* 用的
|
||||
# **预编译**正则(性能:字面量正则预编译避免 re 缓存查找与编译开销)。
|
||||
_RE_T_TYPE_PTR: re.Pattern[str] = re.compile(r'%"[a-f0-9]+\.T"\*')
|
||||
_RE_T_TYPE: re.Pattern[str] = re.compile(r'%"[a-f0-9]+\.T"')
|
||||
|
||||
|
||||
class DeclarationGenerator:
|
||||
"""从 .pyi AST 生成纯 LLVM IR 声明(不使用字符串操作)"""
|
||||
|
||||
@@ -1060,9 +1065,9 @@ class DeclarationGenerator:
|
||||
for mt in member_types:
|
||||
new_mt: str = mt
|
||||
# 将 %"SHA1.T"* 替换为 i8*(不透明指针)
|
||||
new_mt = re.sub(r'%"[a-f0-9]+\.T"\*', 'i8*', new_mt)
|
||||
new_mt = _RE_T_TYPE_PTR.sub('i8*', new_mt)
|
||||
# 将 %"SHA1.T"(非指针,如 embedded struct)替换为 i8*
|
||||
new_mt = re.sub(r'%"[a-f0-9]+\.T"', 'i8*', new_mt)
|
||||
new_mt = _RE_T_TYPE.sub('i8*', new_mt)
|
||||
result.append(new_mt)
|
||||
return result
|
||||
|
||||
|
||||
@@ -235,6 +235,53 @@ _RE_AT_EXTERNAL: re.Pattern[str] = re.compile(r'@\S+\s*=\s*external\s+')
|
||||
_RE_DECLARE_FULL: re.Pattern[str] = re.compile(
|
||||
r'^declare\s+(?:dso_local\s+)?[^@]*@\"?([^"\s\(]+)\"?\s*\(')
|
||||
|
||||
# 其余字面量正则的模块级预编译(同一性能理由:省掉每次调用的"模式串哈希 →
|
||||
# re 缓存查找";模式串一字未改,flags 原样保留)。凡模式串不同或 flags 不同
|
||||
# (有/无 re.MULTILINE)之处都各自独立成常量,保证匹配语义逐字不变。
|
||||
# `_AddWeakComdat`:定位函数头第一个元数据(`!...`)附着点 / 全局定义尾部属性插入点
|
||||
_RE_METADATA_ATTACH: re.Pattern[str] = re.compile(r'\s![\w.]')
|
||||
_RE_COMDAT_TAIL_ATTRS: re.Pattern[str] = re.compile(r',\s*(?:align|section|partition|code_model)\b')
|
||||
# LLVM 22+ external global 带初值 → linkonce(带行首锚 + MULTILINE)
|
||||
_RE_EXTERNAL_GLOBAL_VALUE: re.Pattern[str] = re.compile(
|
||||
r'^(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$',
|
||||
re.MULTILINE)
|
||||
# 同上但**不带行首锚**(opt 内联后整段内容替换处)
|
||||
_RE_EXTERNAL_GLOBAL_VALUE_PLAIN: re.Pattern[str] = re.compile(
|
||||
r'(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$',
|
||||
re.MULTILINE)
|
||||
# define/declare 后跟显式链接性关键字 → 其后补 dso_local
|
||||
_RE_DEFINE_DECLARE_LINKAGE: re.Pattern[str] = re.compile(
|
||||
r'^(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+',
|
||||
re.MULTILINE)
|
||||
# define/declare 后无链接性/dso_local(含 `@` 分支)→ 直接补 dso_local
|
||||
_RE_DEFINE_DECLARE_NO_LINKAGE_AT: re.Pattern[str] = re.compile(
|
||||
r'^(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)',
|
||||
re.MULTILINE)
|
||||
# 同上但**无 `@` 分支**(traceback include 模块专用)
|
||||
_RE_DEFINE_DECLARE_NO_LINKAGE: re.Pattern[str] = re.compile(
|
||||
r'^(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)',
|
||||
re.MULTILINE)
|
||||
# 全局定义(非 llvm.*)带链接性关键字 → 补 dso_local(无 MULTILINE)
|
||||
_RE_GLOBAL_LINKAGE: re.Pattern[str] = re.compile(
|
||||
r'(@(?!llvm\.)[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr)\s+(global|constant)')
|
||||
# 同上但带 MULTILINE
|
||||
_RE_GLOBAL_LINKAGE_MULTILINE: re.Pattern[str] = re.compile(
|
||||
r'(@(?!llvm\.)[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr)\s+(global|constant)',
|
||||
re.MULTILINE)
|
||||
# 全局定义无链接性 → 补 dso_local(无 MULTILINE)
|
||||
_RE_GLOBAL_DSOLOCAL: re.Pattern[str] = re.compile(
|
||||
r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|dso_local)(global|constant)')
|
||||
# 同上但带 MULTILINE(原文此处带行首锚 `^`:避免匹配到字符串常量内容里的 global/constant)
|
||||
_RE_GLOBAL_DSOLOCAL_MULTILINE: re.Pattern[str] = re.compile(
|
||||
r'^(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|dso_local)(global|constant)',
|
||||
re.MULTILINE)
|
||||
# 收集已定义函数名(define 头)
|
||||
_RE_DEFINE_HEAD: re.Pattern[str] = re.compile(
|
||||
r'^define\s+(?:dso_local\s+)?[^@]*@\"?([^"\s\(]+)\"?\s*\(',
|
||||
re.MULTILINE)
|
||||
# 判定 IR 是否含 define 行(traceback 警告)
|
||||
_RE_DEFINE_LINE: re.Pattern[str] = re.compile(r'^define ', re.MULTILINE)
|
||||
|
||||
|
||||
def _ParseDwarfLineRows(dump_text: str) -> list[tuple[int, str, int]]:
|
||||
"""从 llvm-dwarfdump 输出解析出 [(地址, 文件绝对路径, 行号)]。
|
||||
@@ -989,7 +1036,7 @@ def _AddWeakComdat(ll_content: str) -> str:
|
||||
# "expected '{' in function body"(`[^{]*` 会跨行吞掉换行,--dwarf 给
|
||||
# 每个 define 行尾加了 !dbg 后插入点就落到了附着之后)。故插入点前移到
|
||||
# 第一个元数据附着之前。
|
||||
attach = re.search(r'\s![\w.]', head)
|
||||
attach = _RE_METADATA_ATTACH.search(head)
|
||||
if attach is None:
|
||||
return head + ' comdat ' + m.group(4)
|
||||
return head[:attach.start()] + ' comdat' + head[attach.start():] + m.group(4)
|
||||
@@ -1004,7 +1051,7 @@ def _AddWeakComdat(ll_content: str) -> str:
|
||||
if ' comdat' in line:
|
||||
return line
|
||||
comdat_names.append(m.group(3))
|
||||
ins = re.search(r',\s*(?:align|section|partition|code_model)\b', line)
|
||||
ins = _RE_COMDAT_TAIL_ATTRS.search(line)
|
||||
if ins:
|
||||
return line[:ins.start()] + ', comdat' + line[ins.start():]
|
||||
return line + ', comdat'
|
||||
@@ -2285,7 +2332,7 @@ class Phase2Translator:
|
||||
'--traceback: traceback 模块未注入 @llvm.global_ctors '
|
||||
'(模块级收尾钩子未生效,不静默降级)')
|
||||
# 修复 LLVM 22+: external global 不能有初值,改为 linkonce
|
||||
result = re.sub(r'^(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$', r'\1 = linkonce global \2 \3', result, flags=re.MULTILINE)
|
||||
result = _RE_EXTERNAL_GLOBAL_VALUE.sub(r'\1 = linkonce global \2 \3', result)
|
||||
# 后处理:添加 llvmlite 不支持的 LLVM 属性(如 willreturn, mustprogress)
|
||||
pending_str_attrs = getattr(trans.translator.LlvmGen, '_pending_str_attrs', None)
|
||||
if pending_str_attrs:
|
||||
@@ -2524,12 +2571,12 @@ class Phase2Translator:
|
||||
else:
|
||||
_vlog().info(" [内联] 跨模块内联优化完成")
|
||||
opt_content = _ReadTextCached(optimized_ll)
|
||||
opt_content = re.sub(r'^(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', opt_content, flags=re.MULTILINE)
|
||||
opt_content = re.sub(r'^(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', opt_content, flags=re.MULTILINE)
|
||||
opt_content = _RE_DEFINE_DECLARE_LINKAGE.sub(r'\1 \2 dso_local ', opt_content)
|
||||
opt_content = _RE_DEFINE_DECLARE_NO_LINKAGE_AT.sub(r'\1 dso_local ', opt_content)
|
||||
# LLVM 22+: external 不允许在带初值的全局定义上显式写出,改为 linkonce 保留多模块合并语义
|
||||
opt_content = re.sub(r'(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$', r'\1 = linkonce global \2 \3', opt_content, flags=re.MULTILINE)
|
||||
opt_content = re.sub(r'(@(?!llvm\.)[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr)\s+(global|constant)', r'\1 = \2 dso_local \3', opt_content)
|
||||
opt_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|dso_local)(global|constant)', r'\1 = dso_local \2', opt_content)
|
||||
opt_content = _RE_EXTERNAL_GLOBAL_VALUE_PLAIN.sub(r'\1 = linkonce global \2 \3', opt_content)
|
||||
opt_content = _RE_GLOBAL_LINKAGE.sub(r'\1 = \2 dso_local \3', opt_content)
|
||||
opt_content = _RE_GLOBAL_DSOLOCAL.sub(r'\1 = dso_local \2', opt_content)
|
||||
opt_content = _AddWeakComdat(opt_content)
|
||||
with open(optimized_ll, 'w', encoding='utf-8') as f:
|
||||
f.write(opt_content)
|
||||
@@ -2756,16 +2803,16 @@ class Phase2Translator:
|
||||
break
|
||||
ll_lines = ll_content.splitlines(True)
|
||||
ll_content = ''.join(ll_lines[:header_end]) + stub_prefix + ''.join(ll_lines[header_end:])
|
||||
ll_content = re.sub(r'^(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'^(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', ll_content, flags=re.MULTILINE)
|
||||
ll_content = _RE_DEFINE_DECLARE_LINKAGE.sub(r'\1 \2 dso_local ', ll_content)
|
||||
ll_content = _RE_DEFINE_DECLARE_NO_LINKAGE_AT.sub(r'\1 dso_local ', ll_content)
|
||||
# LLVM 22+: external 不允许在带初值的全局定义上显式写出,改为 linkonce 保留多模块合并语义
|
||||
ll_content = re.sub(r'^(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$', r'\1 = linkonce global \2 \3', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'(@(?!llvm\.)[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'^(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content, flags=re.MULTILINE)
|
||||
ll_content = _RE_EXTERNAL_GLOBAL_VALUE.sub(r'\1 = linkonce global \2 \3', ll_content)
|
||||
ll_content = _RE_GLOBAL_LINKAGE_MULTILINE.sub(r'\1 = \2 dso_local \3', ll_content)
|
||||
ll_content = _RE_GLOBAL_DSOLOCAL_MULTILINE.sub(r'\1 = dso_local \2', ll_content)
|
||||
ll_content = _AddWeakComdat(ll_content)
|
||||
# LLVM 22+: 移除同一模块中已有 define 的 declare 语句(LLVM 22 将 declare+define 视为重复定义)
|
||||
defined_funcs: set[str] = set()
|
||||
for m in re.finditer(r'^define\s+(?:dso_local\s+)?[^@]*@\"?([^"\s\(]+)\"?\s*\(', ll_content, re.MULTILINE):
|
||||
for m in _RE_DEFINE_HEAD.finditer(ll_content):
|
||||
defined_funcs.add(m.group(1))
|
||||
if defined_funcs:
|
||||
lines: list[str] = ll_content.splitlines(True)
|
||||
@@ -3622,19 +3669,19 @@ class Phase2Translator:
|
||||
# **只警告、不报错**:像 includes/stdarg.vp 这类模块的 define 是"合成"的
|
||||
# (由 extern/sugar 派生、无 .vp 函数体),本就不会有源级 DI —— 按 fail-fast
|
||||
# 报错会把这类模块全部误杀;而"行号缺失"只降低可读性,不是编译正确性问题。
|
||||
if self.traceback_enabled and re.search(r'^define ', ll_content, re.MULTILINE) \
|
||||
if self.traceback_enabled and _RE_DEFINE_LINE.search(ll_content) \
|
||||
and '!llvm.dbg.cu' not in ll_content:
|
||||
_vlog().warning(
|
||||
f"--traceback: include 模块 {module_name}.py 发射了 define 但 IR 未携带 "
|
||||
f"DWARF (!llvm.dbg.cu)——该模块内联帧在 Ctrl+C 栈里将只显示地址: {ll_path}")
|
||||
|
||||
# dso_local 正则标注(使用 ^ + MULTILINE 避免匹配字符串常量内容中的 define/declare)
|
||||
ll_content = re.sub(r'^(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'^(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)', r'\1 dso_local ', ll_content, flags=re.MULTILINE)
|
||||
ll_content = _RE_DEFINE_DECLARE_LINKAGE.sub(r'\1 \2 dso_local ', ll_content)
|
||||
ll_content = _RE_DEFINE_DECLARE_NO_LINKAGE.sub(r'\1 dso_local ', ll_content)
|
||||
# LLVM 22+: external 不允许在带初值的全局定义上显式写出,改为 linkonce 保留多模块合并语义
|
||||
ll_content = re.sub(r'^(@[\w.]+)\s*=\s*external\s+global\s+(\w[\w*]*)\s+(-?\d+|null|zeroinitializer|true|false)$', r'\1 = linkonce global \2 \3', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'(@(?!llvm\.)[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content, flags=re.MULTILINE)
|
||||
ll_content = re.sub(r'^(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content, flags=re.MULTILINE)
|
||||
ll_content = _RE_EXTERNAL_GLOBAL_VALUE.sub(r'\1 = linkonce global \2 \3', ll_content)
|
||||
ll_content = _RE_GLOBAL_LINKAGE_MULTILINE.sub(r'\1 = \2 dso_local \3', ll_content)
|
||||
ll_content = _RE_GLOBAL_DSOLOCAL_MULTILINE.sub(r'\1 = dso_local \2', ll_content)
|
||||
ll_content = _AddWeakComdat(ll_content)
|
||||
|
||||
# stub_decls 注入(复用预收集的 stub_decls)
|
||||
|
||||
Reference in new issue
Block a user