fix(exprcall): 兄弟 Mixin 兜底仅对组合类父类启用——防误绑 HashTable 方法

3fd875d 只过滤了 list 特化类名,普通类(HashTable)仍被误绑:JsonValue.__getitem__ 未命中时遍历 class_methods 命中 HashTable.__getitem__,this 前移 sizeof(HashTable)=-48 → Load_project_config root.__getitem__ 读 -1 崩溃(1.LOG 4c1f8f779b98eab9.HashTable._slot_hash)。

加固:兜底前检查 class_name 是否是多继承组合类的父类(存在以它为父类的类,如 Generator 的 44 个 Mixin / Combined(BaseA,BaseB))。普通类方法未命中时不再回退到无关类,走 fail-fast(Undefined method)暴露上游 stub 注册/时序问题。
This commit is contained in:
TermiNexus committed 2026-08-20 17:08:14 +08:00
1 parent 51c0e026f4
commit 780cd4a13b
1 file changed
+36 -15
+36 -15
View File
@@ -3176,21 +3176,42 @@ class ExprCallHandle(BaseHandle):
# 方法调用在找不到时会误绑定到 list 特化函数,this 按 list 布局
# 前移 sizeof(list) → 运行期读 -1 崩溃(Config.vp 的
# root.__getitem__ 根因,与 TPV CallGenCall.vp 兜底修复一致)。
for _cand_cls, _cand_methods in list(Gen.class_methods.items()):
if _cand_cls == ClassName:
continue
if '[' in _cand_cls:
continue
if not any(_cm.endswith(f'.{MethodName}') or _cm == MethodName for _cm in _cand_methods):
continue
_cand_full = f'{_cand_cls}.{MethodName}'
_cand_func = Gen._find_function(_cand_full)
if not _cand_func:
_cand_func = Gen._find_function(f'{_cand_full}__')
if _cand_func:
func = _cand_func
method_anc = _cand_cls
break
# 进一步加固:兄弟 Mixin 兜底仅在 class_name 是多继承组合类的
# 父类(存在以 class_name 为父类的类,如 Generator 的 44 个 Mixin /
# Combined(BaseA, BaseB))时才启用。普通类(JsonValue 等)方法
# 未命中时不应回退到无关类——3fd875d 只过滤了 list 特化,
# HashTable.__getitem__ 仍被误绑(JsonValue.__getitem__ 未命中时
# 遍历 class_methods 命中 HashTable),this 前移 sizeof(HashTable)
# =-48 → Load_project_config root.__getitem__ 读 -1 崩溃
# (1.LOG 4c1f8f779b98eab9.HashTable._slot_hash)。
_is_mixin_parent: bool = False
try:
for _s_cls in Gen.structs:
if _s_cls == ClassName:
continue
if '[' in _s_cls:
continue
if ClassName in Gen._get_mro_chain(_s_cls):
_is_mixin_parent = True
break
except Exception:
_is_mixin_parent = False
if _is_mixin_parent:
for _cand_cls, _cand_methods in list(Gen.class_methods.items()):
if _cand_cls == ClassName:
continue
if '[' in _cand_cls:
continue
if not any(_cm.endswith(f'.{MethodName}') or _cm == MethodName for _cm in _cand_methods):
continue
_cand_full = f'{_cand_cls}.{MethodName}'
_cand_func = Gen._find_function(_cand_full)
if not _cand_func:
_cand_func = Gen._find_function(f'{_cand_full}__')
if _cand_func:
func = _cand_func
method_anc = _cand_cls
break
if func:
# 多继承 this 调整:继承方法定义在无 vtable 父类且字段区偏移 > 0 时,
# 把 self 定位到父类第一个用户字段在子类中的位置并 bitcast 成父类指针。