Commit f2e76c65 authored by Claudio Freire's avatar Claudio Freire

Add no_gc directive to fully disable GC

Useful when one can guarantee the class cannot participate in
cycles, but the compiler cannot prove it on its own
parent ef57fb78
...@@ -116,6 +116,7 @@ directive_defaults = { ...@@ -116,6 +116,7 @@ directive_defaults = {
'internal' : False, 'internal' : False,
'profile': False, 'profile': False,
'no_gc_clear': False, 'no_gc_clear': False,
'no_gc': False,
'linetrace': False, 'linetrace': False,
'emit_code_comments': True, # copy original source code into C code comments 'emit_code_comments': True, # copy original source code into C code comments
'annotation_typing': False, # read type declarations from Python function annotations 'annotation_typing': False, # read type declarations from Python function annotations
...@@ -246,6 +247,7 @@ directive_scopes = { # defaults to available everywhere ...@@ -246,6 +247,7 @@ directive_scopes = { # defaults to available everywhere
'inline' : ('function',), 'inline' : ('function',),
'staticmethod' : ('function',), # FIXME: analysis currently lacks more specific function scope 'staticmethod' : ('function',), # FIXME: analysis currently lacks more specific function scope
'no_gc_clear' : ('cclass',), 'no_gc_clear' : ('cclass',),
'no_gc' : ('cclass',),
'internal' : ('cclass',), 'internal' : ('cclass',),
'autotestdict' : ('module',), 'autotestdict' : ('module',),
'autotestdict.all' : ('module',), 'autotestdict.all' : ('module',),
......
...@@ -1889,7 +1889,7 @@ class CClassScope(ClassScope): ...@@ -1889,7 +1889,7 @@ class CClassScope(ClassScope):
def needs_gc(self): def needs_gc(self):
# If the type or any of its base types have Python-valued # If the type or any of its base types have Python-valued
# C attributes, then it needs to participate in GC. # C attributes, then it needs to participate in GC.
if self.has_cyclic_pyobject_attrs: if self.has_cyclic_pyobject_attrs and not self.directives.get('no_gc', False):
return True return True
base_type = self.parent_type.base_type base_type = self.parent_type.base_type
if base_type and base_type.scope is not None: if base_type and base_type.scope is not None:
......
...@@ -118,7 +118,7 @@ optimization = _Optimization() ...@@ -118,7 +118,7 @@ optimization = _Optimization()
overflowcheck.fold = optimization.use_switch = \ overflowcheck.fold = optimization.use_switch = \
optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager() optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()
final = internal = type_version_tag = no_gc_clear = _empty_decorator final = internal = type_version_tag = no_gc_clear = no_gc = _empty_decorator
def inline(f, *args, **kwds): def inline(f, *args, **kwds):
......
"""
Check that the @cython.no_gc decorator disables generation of the
tp_clear and tp_traverse slots, that is, disables cycle collection.
"""
cimport cython
from cpython.ref cimport PyObject, Py_TYPE
# Force non-gc'd PyTypeObject when safety is guaranteed by user but not provable
cdef extern from *:
ctypedef struct PyTypeObject:
void (*tp_clear)(object)
void (*tp_traverse)(object)
def is_tp_clear_null(obj):
return (<PyTypeObject*>Py_TYPE(obj)).tp_clear is NULL
def is_tp_traverse_null(obj):
return (<PyTypeObject*>Py_TYPE(obj)).tp_traverse is NULL
@cython.no_gc
cdef class DisableGC:
"""
An extension type that has a tp_clear method generated to test that it
actually clears the references to NULL.
>>> uut = DisableGC()
>>> is_tp_clear_null(uut)
True
>>> is_tp_traverse_null(uut)
True
"""
cdef public object requires_cleanup
def __cinit__(self):
self.requires_cleanup = (
"Tuples to strings don't really need cleanup, cannot take part of cycles",)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment