diff --git a/llvmlite/__function.vp b/llvmlite/__function.vp index 28ed2b5..83f7d17 100644 --- a/llvmlite/__function.vp +++ b/llvmlite/__function.vp @@ -694,15 +694,18 @@ def _peep_replace_token(pool: rowptr[memhub.MemBuddy], return line_buf if tlen == 0: return line_buf - ln: t.CSizeT = string.strlen(line_buf) - # 预扫是否命中 + # 预扫是否命中:不依赖 strlen,以 NUL 为界单趟扫描(绝大多数调用无命中即返回, + # 从而省去逐行 strlen)。逐输入等价:tok 无 NUL(tlen=strlen(tok)),故 + # strncmp 判等必蕴含记号完整落在串内(i+tlen 处仍非 NUL);凡 i+tlen>ln 的 + # 位置 strncmp 必先遇到 line_buf 的 NUL 而与 tok 的非 NUL 字节不等,故原 + # 上界 i+tlen<=ln 从未排除任一可能命中,去掉后命中判定不变。 hit: int = 0 i: t.CSizeT = 0 - while i + tlen <= ln: + while line_buf[i] != '\0': if line_buf[i] == '%' and line_buf[i + 1] == tok[0] \ and string.strncmp(line_buf + i + 1, tok, tlen) == 0: nxt: int = 0 - if i + 1 + tlen < ln: + if line_buf[i + 1 + tlen] != '\0': cc: int = line_buf[i + 1 + tlen] if (cc >= 48 and cc <= 57) or (cc >= 65 and cc <= 90) or (cc >= 97 and cc <= 122) or cc == 95: nxt = 1 @@ -712,6 +715,7 @@ def _peep_replace_token(pool: rowptr[memhub.MemBuddy], i += 1 if hit == 0: return line_buf + ln: t.CSizeT = string.strlen(line_buf) # 缓冲大小上界:单行最多 ⌊ln/2⌋ 次替换,每次去掉 ≥2 字节(%+名)换入 rlen 字节; # 最坏输出 ≤ ln + (ln/2)·rlen + NUL。ln + 1 + rlen·(ln+1) 恒覆盖该上界, # 避免 K≥2 且替换串更长时把新缓冲写穿(随机内存破坏)。 @@ -801,6 +805,11 @@ def _peep_is_alloc_of(eb: str, a_name: str, nl: t.CSizeT) -> int: """ if eb is None or a_name is None or nl == 0 or eb[0] != '%': return 0 + # 首字符预筛:nl>=1,strncmp 判等必然蕴含首字符相等;首字符不同即可廉价拒绝, + # 避免绝大多数行进入 strncmp 调用。逐输入等价:本分支拒绝当且仅当原 strncmp + # 也必返回非 0(首字节不同)。eb[0]=='%' 非 NUL ⇒ eb[1] 读在串内(最多为 NUL)。 + if eb[1] != a_name[0]: + return 0 if string.strncmp(eb + 1, a_name, nl) != 0: return 0 eqpos: str = string.strstr(eb, " = alloca ") @@ -997,7 +1006,7 @@ def _peephole_opt(func: rowptr[Function], pool: rowptr[memhub.MemBuddy]): db: str = ld.Buf if db is not None: kill: int = 0 - if db[0] == '%': + if db[0] == '%' and db[1] == a_name[0]: if _peep_is_alloc_of(db, a_name, a_name_len) != 0: kill = 1 if kill == 0 and _peep_last_ref_eq(db, a_name, a_name_len) != 0: