From 671a27d56bd67d392c68a7c03634ff98fc198104 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sat, 2 May 2026 09:43:22 +0800 Subject: [PATCH 1/2] gh-149217: Avoid adding dependencies on immutable, immortal classes in the JIT --- Python/optimizer_analysis.c | 22 ++++++++++++++-------- Python/optimizer_bytecodes.c | 15 +++++---------- Python/optimizer_cases.c.h | 15 +++++---------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 9f6ce206ef4722..1dc3a248f45f0c 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -156,6 +156,16 @@ type_watcher_callback(PyTypeObject* type) return 0; } +static void +watch_type(PyTypeObject *type, _PyBloomFilter *filter) +{ + if (_Py_IsImmortal(type) && (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) { + return; + } + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(filter, type); +} + static PyObject * convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj) { @@ -367,8 +377,7 @@ optimize_dict_known_hash( // for user-defined objects which don't override tp_hash Py_hash_t hash = PyObject_Hash(sub); ADD_OP(opcode, 0, hash); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)Py_TYPE(sub)); - _Py_BloomFilter_Add(dependencies, Py_TYPE(sub)); + watch_type(Py_TYPE(sub), dependencies); } } @@ -401,8 +410,7 @@ lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction ADD_OP(suffix, 2, 0); } if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); + watch_type(type, dependencies); } return sym_new_const(ctx, lookup); } @@ -473,10 +481,8 @@ lookup_super_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, } // if obj_type is immutable, then all its superclasses are immutable if ((obj_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)su_type); - _Py_BloomFilter_Add(dependencies, su_type); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)obj_type); - _Py_BloomFilter_Add(dependencies, obj_type); + watch_type(su_type, dependencies); + watch_type(obj_type, dependencies); } return sym_new_const_steal(ctx, lookup); } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 33b5257fd58281..9866baedd6074b 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -148,8 +148,7 @@ dummy_func(void) { sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); + watch_type(probable_type, dependencies); } } else { @@ -237,8 +236,7 @@ dummy_func(void) { else { sym_set_const(owner, type); if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, type); - _Py_BloomFilter_Add(dependencies, type); + watch_type((PyTypeObject *)type, dependencies); } } } @@ -256,8 +254,7 @@ dummy_func(void) { probable_type->tp_version_tag == type_version) { sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -1318,8 +1315,7 @@ dummy_func(void) { assert(init != NULL); assert(PyFunction_Check(init)); callable = sym_new_const(ctx, init); - PyType_Watch(TYPE_WATCHER_ID, callable_o); - _Py_BloomFilter_Add(dependencies, callable_o);; + watch_type((PyTypeObject *)callable_o, dependencies); } else { callable = sym_new_not_null(ctx); @@ -2026,8 +2022,7 @@ dummy_func(void) { ADD_OP(_SWAP, 3, 0); optimize_pop_top(ctx, this_instr, method_and_self[0]); if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); + watch_type(type, dependencies); } method_and_self[0] = sym_new_const(ctx, descr); optimized = true; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 8f208beb86476b..6c51bbcd7d5d6b 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2528,8 +2528,7 @@ probable_type->tp_version_tag == type_version) { sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -2555,8 +2554,7 @@ sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); + watch_type(probable_type, dependencies); } } else { @@ -2684,8 +2682,7 @@ else { sym_set_const(owner, type); if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, type); - _Py_BloomFilter_Add(dependencies, type); + watch_type((PyTypeObject *)type, dependencies); } } } @@ -3776,8 +3773,7 @@ ADD_OP(_SWAP, 3, 0); optimize_pop_top(ctx, this_instr, method_and_self[0]); if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); + watch_type(type, dependencies); } method_and_self[0] = sym_new_const(ctx, descr); optimized = true; @@ -4314,8 +4310,7 @@ assert(PyFunction_Check(init)); callable = sym_new_const(ctx, init); stack_pointer[-2 - oparg] = callable; - PyType_Watch(TYPE_WATCHER_ID, callable_o); - _Py_BloomFilter_Add(dependencies, callable_o);; + watch_type((PyTypeObject *)callable_o, dependencies); } else { callable = sym_new_not_null(ctx); From bdd2f60aac0927ca5c164b5e65b3b80c8b56f41e Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sun, 3 May 2026 16:19:05 +0800 Subject: [PATCH 2/2] fix --- Python/optimizer_bytecodes.c | 12 +++--------- Python/optimizer_cases.c.h | 12 +++--------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 9866baedd6074b..c9cda3f5529239 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -147,9 +147,7 @@ dummy_func(void) { // Promote the probable type version to a known one. sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); - if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type(probable_type, dependencies); - } + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -235,9 +233,7 @@ dummy_func(void) { } else { sym_set_const(owner, type); - if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type((PyTypeObject *)type, dependencies); - } + watch_type((PyTypeObject *)type, dependencies); } } } @@ -2021,9 +2017,7 @@ dummy_func(void) { 0, (uintptr_t)descr); ADD_OP(_SWAP, 3, 0); optimize_pop_top(ctx, this_instr, method_and_self[0]); - if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type(type, dependencies); - } + watch_type(type, dependencies); method_and_self[0] = sym_new_const(ctx, descr); optimized = true; } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 6c51bbcd7d5d6b..8ae4c68c7875f2 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2553,9 +2553,7 @@ probable_type->tp_version_tag == type_version) { sym_set_type(owner, probable_type); sym_set_type_version(owner, type_version); - if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type(probable_type, dependencies); - } + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -2681,9 +2679,7 @@ } else { sym_set_const(owner, type); - if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type((PyTypeObject *)type, dependencies); - } + watch_type((PyTypeObject *)type, dependencies); } } break; @@ -3772,9 +3768,7 @@ 0, (uintptr_t)descr); ADD_OP(_SWAP, 3, 0); optimize_pop_top(ctx, this_instr, method_and_self[0]); - if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { - watch_type(type, dependencies); - } + watch_type(type, dependencies); method_and_self[0] = sym_new_const(ctx, descr); optimized = true; }