From 8a7eddaa84e1880023ec75ed8af4d1836d9b5ed2 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sun, 3 May 2026 18:06:39 +0800 Subject: [PATCH] gh-149217: Avoid adding dependencies on immutable, immortal classes in the JIT (GH149256) --- Python/optimizer_analysis.c | 22 ++++++++++++++-------- Python/optimizer_bytecodes.c | 21 +++++---------------- Python/optimizer_cases.c.h | 21 +++++---------------- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 9f6ce206ef4..1dc3a248f45 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 fa34fe4cbb3..0837d57b61b 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -149,10 +149,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) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); - } + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -238,10 +235,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); } } } @@ -258,8 +252,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; @@ -1326,8 +1319,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); @@ -2033,10 +2025,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) { - 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 553bd730202..1ade86f64b2 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2534,8 +2534,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; @@ -2560,10 +2559,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) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); - _Py_BloomFilter_Add(dependencies, probable_type); - } + watch_type(probable_type, dependencies); } else { ctx->contradiction = true; @@ -2689,10 +2685,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); } } break; @@ -3781,10 +3774,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) { - 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; } @@ -4320,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);