summaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Compiler
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler')
-rw-r--r--contrib/tools/cython/Cython/Compiler/Code.py11
-rw-r--r--contrib/tools/cython/Cython/Compiler/ModuleNode.py11
-rw-r--r--contrib/tools/cython/Cython/Compiler/Scanning.py9
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):