Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
cython
Commits
232d3cab
Commit
232d3cab
authored
Feb 23, 2013
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement freelist support for extension types with a @cython.freelist(N) decorator
parent
74657f01
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
133 additions
and
15 deletions
+133
-15
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+57
-14
Cython/Compiler/Naming.py
Cython/Compiler/Naming.py
+2
-0
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+4
-1
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+5
-0
tests/run/exttype_freelist.pyx
tests/run/exttype_freelist.pyx
+65
-0
No files found.
Cython/Compiler/ModuleNode.py
View file @
232d3cab
...
...
@@ -1033,34 +1033,52 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else
:
unused_marker
=
'CYTHON_UNUSED '
if
base_type
:
freelist_size
=
0
# not currently supported
else
:
freelist_size
=
scope
.
directives
.
get
(
'freelist'
,
0
)
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
decls
=
code
.
globalstate
[
'decls'
]
decls
.
putln
(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/"
%
slot_func
)
code
.
putln
(
""
)
if
freelist_size
:
code
.
putln
(
"static %s[%d];"
%
(
scope
.
parent_type
.
declaration_code
(
freelist_name
),
freelist_size
))
code
.
putln
(
"static int %s = 0;"
%
freecount_name
)
code
.
putln
(
""
)
code
.
putln
(
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {"
%
(
slot_func
,
unused_marker
,
unused_marker
))
need_self_cast
=
type
.
vtabslot_cname
or
have_entries
or
cpp_class_attrs
if
need_self_cast
:
code
.
putln
(
"%s;"
%
scope
.
parent_type
.
declaration_code
(
"p"
))
code
.
putln
(
"%s;"
%
scope
.
parent_type
.
declaration_code
(
"p"
))
if
base_type
:
tp_new
=
TypeSlots
.
get_base_slot_function
(
scope
,
tp_slot
)
if
tp_new
is
None
:
tp_new
=
"%s->tp_new"
%
base_type
.
typeptr_cname
code
.
putln
(
"PyObject *o = %s(t, a, k);"
%
tp_new
)
code
.
putln
(
"PyObject *o = %s(t, a, k);"
%
tp_new
)
else
:
code
.
putln
(
"PyObject *o = (*t->tp_alloc)(t, 0);"
)
code
.
putln
(
"if (!o) return 0;"
)
code
.
putln
(
"PyObject *o;"
)
if
freelist_size
:
code
.
putln
(
"if ((%s > 0) & (t == %s)) {"
%
(
freecount_name
,
type
.
typeptr_cname
))
code
.
putln
(
"o = (PyObject*)%s[--%s];"
%
(
freelist_name
,
freecount_name
))
code
.
putln
(
"PyObject_Init(o, t);"
)
if
scope
.
needs_gc
():
code
.
putln
(
"PyObject_GC_Track(o);"
)
code
.
putln
(
"} else {"
)
code
.
putln
(
"o = (*t->tp_alloc)(t, 0);"
)
code
.
putln
(
"if (!o) return 0;"
)
if
freelist_size
and
not
base_type
:
code
.
putln
(
'}'
)
if
need_self_cast
:
code
.
putln
(
"p = %s;"
%
type
.
cast_code
(
"o"
))
code
.
putln
(
"p = %s;"
%
type
.
cast_code
(
"o"
))
#if need_self_cast:
# self.generate_self_cast(scope, code)
if
type
.
vtabslot_cname
:
...
...
@@ -1184,8 +1202,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CallNextTpDealloc"
,
"ExtensionTypes.c"
))
else
:
code
.
putln
(
"(*Py_TYPE(o)->tp_free)(o);"
)
freelist_size
=
scope
.
directives
.
get
(
'freelist'
,
0
)
if
freelist_size
:
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
type
=
scope
.
parent_type
code
.
putln
(
"if ((%s < %d) & (Py_TYPE(o) == %s)) {"
%
(
freecount_name
,
freelist_size
,
type
.
typeptr_cname
))
code
.
putln
(
"%s[%s++] = %s;"
%
(
freelist_name
,
freecount_name
,
type
.
cast_code
(
"o"
)))
code
.
putln
(
"} else {"
)
code
.
putln
(
"(*Py_TYPE(o)->tp_free)(o);"
)
if
freelist_size
:
code
.
putln
(
"}"
)
code
.
putln
(
"}"
)
...
...
@@ -2038,6 +2068,19 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
PyrexTypes
.
py_object_type
,
clear_before_decref
=
True
,
nanny
=
False
)
for
entry
in
env
.
c_class_entries
:
cclass_type
=
entry
.
type
if
cclass_type
.
base_type
:
continue
if
cclass_type
.
scope
.
directives
.
get
(
'freelist'
,
0
):
scope
=
cclass_type
.
scope
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
code
.
putln
(
"while (%s > 0) {"
%
freecount_name
)
code
.
putln
(
"PyObject* o = (PyObject*)%s[--%s];"
%
(
freelist_name
,
freecount_name
))
code
.
putln
(
"(*Py_TYPE(o)->tp_free)(o);"
)
code
.
putln
(
"}"
)
# for entry in env.pynum_entries:
# code.put_decref_clear(entry.cname,
# PyrexTypes.py_object_type,
...
...
Cython/Compiler/Naming.py
View file @
232d3cab
...
...
@@ -103,6 +103,8 @@ global_code_object_cache_find = pyrex_prefix + 'find_code_object'
global_code_object_cache_insert
=
pyrex_prefix
+
'insert_code_object'
genexpr_id_ref
=
'genexpr'
freelist_name
=
'freelist'
freecount_name
=
'freecount'
line_c_macro
=
"__LINE__"
...
...
Cython/Compiler/Options.py
View file @
232d3cab
...
...
@@ -123,7 +123,8 @@ directive_defaults = {
# experimental, subject to change
'binding'
:
None
,
'experimental_cpp_class_def'
:
False
'experimental_cpp_class_def'
:
False
,
'freelist'
:
0
,
}
# Extra warning directives
...
...
@@ -144,6 +145,7 @@ directive_types = {
'cclass'
:
None
,
'returns'
:
type
,
'set_initial_path'
:
str
,
'freelist'
:
int
,
}
for
key
,
val
in
directive_defaults
.
items
():
...
...
@@ -160,6 +162,7 @@ directive_scopes = { # defaults to available everywhere
'set_initial_path'
:
(
'module'
,),
'test_assert_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
'test_fail_if_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
'freelist'
:
(
'cclass'
,),
}
def
parse_directive_value
(
name
,
value
,
relaxed_bool
=
False
):
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
232d3cab
...
...
@@ -883,6 +883,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
raise
PostParseError
(
pos
,
'The %s directive takes one compile-time boolean argument'
%
optname
)
return
(
optname
,
args
[
0
].
value
)
elif
directivetype
is
int
:
if
kwds
is
not
None
or
len
(
args
)
!=
1
or
not
isinstance
(
args
[
0
],
ExprNodes
.
IntNode
):
raise
PostParseError
(
pos
,
'The %s directive takes one compile-time integer argument'
%
optname
)
return
(
optname
,
int
(
args
[
0
].
value
))
elif
directivetype
is
str
:
if
kwds
is
not
None
or
len
(
args
)
!=
1
or
not
isinstance
(
args
[
0
],
(
ExprNodes
.
StringNode
,
ExprNodes
.
UnicodeNode
)):
...
...
tests/run/exttype_freelist.pyx
0 → 100644
View file @
232d3cab
cimport
cython
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeNoGC
:
"""
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
"""
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeWithGC
:
"""
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
"""
cdef
attribute
def
__init__
(
self
):
self
.
attribute
=
object
()
def
tpnew_ExtTypeWithGC
():
"""
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
"""
return
ExtTypeWithGC
.
__new__
(
ExtTypeWithGC
)
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeWithRefCycle
:
"""
>>> obj = first = ExtTypeWithRefCycle()
>>> obj.attribute is None
True
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj.attribute is first
True
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj.attribute is not None
True
>>> first.attribute = obj
>>> del obj
"""
cdef
public
attribute
def
__init__
(
self
,
obj
=
None
):
self
.
attribute
=
obj
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment