diff options
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler')
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/Code.py | 11 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/ModuleNode.py | 11 | ||||
| -rw-r--r-- | contrib/tools/cython/Cython/Compiler/Scanning.py | 9 |
3 files changed, 25 insertions, 6 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/Code.py b/contrib/tools/cython/Cython/Compiler/Code.py index 630683bf166..ed783164ff8 100644 --- a/contrib/tools/cython/Cython/Compiler/Code.py +++ b/contrib/tools/cython/Cython/Compiler/Code.py @@ -2429,19 +2429,26 @@ class GlobalState: writer.putln("{") writer.putln(f"PyObject **table = {array_cname};") writer.putln(f"for (Py_ssize_t i=0; i<{constant_count}; ++i) {{") - writer.putln("#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING") + writer.putln("#if PY_VERSION_HEX >= 0x030F0000") + writer.putln("PyUnstable_SetImmortal(table[i]);") + writer.putln("#elif CYTHON_COMPILING_IN_CPYTHON_FREETHREADING") # We don't want to set the refcount on shared constants (e.g. cached integers) # because setting the refcount isn't thread-safe. The chances are that most of the constants # that this applies to are already immortal though so that isn't a great loss. + # Overflow, e.g. on 32 bit systems. + writer.putln("if ((PY_SSIZE_T_MAX <= _Py_IMMORTAL_REFCNT_LOCAL)) break;") writer.putln("#if PY_VERSION_HEX < 0x030E0000") writer.putln("if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)") writer.putln("#else") writer.putln("if (PyUnstable_Object_IsUniquelyReferenced(table[i]))") writer.putln("#endif") writer.putln("{") - writer.putln("Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);") + # Go one higher than we think we need to because of a bug in SET_REFCNT check in CPython + writer.putln("Py_SET_REFCNT(table[i], ((Py_ssize_t)_Py_IMMORTAL_REFCNT_LOCAL + 1));") writer.putln("}") writer.putln("#else") + # Overflow, e.g. on 32 bit systems. + writer.putln("if ((PY_SSIZE_T_MAX < _Py_IMMORTAL_INITIAL_REFCNT)) break;") writer.putln("Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);") writer.putln("#endif") writer.putln("}") # for() diff --git a/contrib/tools/cython/Cython/Compiler/ModuleNode.py b/contrib/tools/cython/Cython/Compiler/ModuleNode.py index eb683f8249d..a14f3e9e2ee 100644 --- a/contrib/tools/cython/Cython/Compiler/ModuleNode.py +++ b/contrib/tools/cython/Cython/Compiler/ModuleNode.py @@ -2020,14 +2020,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): if not entry or not entry.is_special: return + code.globalstate.use_utility_code( + UtilityCode.load_cached("DeallocKeepAlive", "ExtensionTypes.c")) code.putln("{") code.putln("PyObject *etype, *eval, *etb;") code.putln("PyErr_Fetch(&etype, &eval, &etb);") - # increase the refcount while we are calling into user code - # to prevent recursive deallocation - code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);") + # Keep the object alive while we are calling into user code, to prevent + # the user code from triggering recursive deallocation. On free-threading + # this must not use Py_SET_REFCNT() (see DeallocKeepAlive in ExtensionTypes.c). + code.putln("__Pyx_DeallocKeepAliveBegin(o);") code.putln("%s(o);" % entry.func_cname) - code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);") + code.putln("__Pyx_DeallocKeepAliveEnd(o);") code.putln("PyErr_Restore(etype, eval, etb);") code.putln("}") diff --git a/contrib/tools/cython/Cython/Compiler/Scanning.py b/contrib/tools/cython/Cython/Compiler/Scanning.py index d63c1263f27..d843960dd17 100644 --- a/contrib/tools/cython/Cython/Compiler/Scanning.py +++ b/contrib/tools/cython/Cython/Compiler/Scanning.py @@ -278,6 +278,15 @@ class StringSourceDescriptor(SourceDescriptor): return "<StringSourceDescriptor:%s>" % self.name +class SharedUtilitySourceDescriptor(FileSourceDescriptor): + """ + A specialized source descriptor for shared utility code only. Not part of public API. + """ + + def get_file_object(self, encoding=None, error_handling=None): + from io import StringIO + return StringIO('') + #------------------------------------------------------------------ class PyrexScanner(Scanner): |
