Commit 36d99d96 authored by Stefan Behnel's avatar Stefan Behnel

avoid keeping a module reference in the CyFunction struct as long as we don't...

avoid keeping a module reference in the CyFunction struct as long as we don't really need it (func_globals isn't really an every days API)
parent e79c5430
...@@ -8795,9 +8795,6 @@ proto=""" ...@@ -8795,9 +8795,6 @@ proto="""
""") """)
# TODO: __Pyx_CyFunction_NewEx implicitly uses the global module
# to get func_globals. This will need to be passed in if we share
# this type accross modules.
binding_cfunc_utility_code = UtilityCode( binding_cfunc_utility_code = UtilityCode(
proto=""" proto="""
#define __Pyx_CyFunction_USED 1 #define __Pyx_CyFunction_USED 1
...@@ -8809,7 +8806,6 @@ typedef struct { ...@@ -8809,7 +8806,6 @@ typedef struct {
PyObject *func_weakreflist; PyObject *func_weakreflist;
PyObject *func_name; PyObject *func_name;
PyObject *func_doc; PyObject *func_doc;
PyObject *func_globals;
} __pyx_CyFunctionObject; } __pyx_CyFunctionObject;
static PyTypeObject *__pyx_CyFunctionType = 0; static PyTypeObject *__pyx_CyFunctionType = 0;
...@@ -8820,7 +8816,7 @@ static int __Pyx_CyFunction_init(void); ...@@ -8820,7 +8816,7 @@ static int __Pyx_CyFunction_init(void);
""" % Naming.__dict__, """ % Naming.__dict__,
impl=""" impl="""
static PyObject * static PyObject *
__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure) __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
{ {
if (op->func_doc == NULL && op->func.m_ml->ml_doc) { if (op->func_doc == NULL && op->func.m_ml->ml_doc) {
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -8886,7 +8882,7 @@ __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value) ...@@ -8886,7 +8882,7 @@ __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value)
} }
static PyObject * static PyObject *
__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, void *closure) __Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure)
{ {
PyObject *self; PyObject *self;
...@@ -8930,21 +8926,24 @@ __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value) ...@@ -8930,21 +8926,24 @@ __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
Py_XDECREF(tmp); Py_XDECREF(tmp);
return 0; return 0;
} }
""" + (
# TODO: we implicitly use the global module to get func_globals. This
# will need to be passed into __Pyx_CyFunction_NewEx() if we share
# this type accross modules. We currently avoid doing this to reduce
# the overhead of creating a function object, and to avoid keeping a
# reference to the module dict as long as we don't need to.
"""
static PyObject * static PyObject *
__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op) __Pyx_CyFunction_get_globals(CYTHON_UNUSED __pyx_CyFunctionObject *op)
{ {
if (op->func_globals == NULL) { PyObject* dict = PyModule_GetDict(%(module_cname)s);
op->func_globals = PyDict_New(); Py_XINCREF(dict);
if (op->func_globals == NULL) return dict;
return NULL;
}
Py_INCREF(op->func_globals);
return op->func_globals;
} }
""" % Naming.__dict__ ) +
"""
static PyObject * static PyObject *
__Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op) __Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op)
{ {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -9003,7 +9002,6 @@ static PyObject *__Pyx_CyFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObjec ...@@ -9003,7 +9002,6 @@ static PyObject *__Pyx_CyFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObjec
op->func_dict = NULL; op->func_dict = NULL;
op->func_name = NULL; op->func_name = NULL;
op->func_doc = NULL; op->func_doc = NULL;
op->func_globals = PyObject_GetAttrString(%(module_cname)s, (char *)"__dict__");
PyObject_GC_Track(op); PyObject_GC_Track(op);
return (PyObject *)op; return (PyObject *)op;
} }
...@@ -9018,7 +9016,6 @@ static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) ...@@ -9018,7 +9016,6 @@ static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
Py_XDECREF(m->func_dict); Py_XDECREF(m->func_dict);
Py_XDECREF(m->func_name); Py_XDECREF(m->func_name);
Py_XDECREF(m->func_doc); Py_XDECREF(m->func_doc);
Py_XDECREF(m->func_globals);
PyObject_GC_Del(m); PyObject_GC_Del(m);
} }
...@@ -9029,7 +9026,6 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, ...@@ -9029,7 +9026,6 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
Py_VISIT(m->func_dict); Py_VISIT(m->func_dict);
Py_VISIT(m->func_name); Py_VISIT(m->func_name);
Py_VISIT(m->func_doc); Py_VISIT(m->func_doc);
Py_VISIT(m->func_globals);
return 0; return 0;
} }
...@@ -9046,10 +9042,10 @@ __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) ...@@ -9046,10 +9042,10 @@ __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
PyObject *func_name = __Pyx_CyFunction_get_name(op); PyObject *func_name = __Pyx_CyFunction_get_name(op);
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
return PyUnicode_FromFormat("<cyfunction %%U at %%p>", return PyUnicode_FromFormat("<cyfunction %U at %p>",
func_name, op); func_name, op);
#else #else
return PyString_FromFormat("<cyfunction %%s at %%p>", return PyString_FromFormat("<cyfunction %s at %p>",
PyString_AsString(func_name), op); PyString_AsString(func_name), op);
#endif #endif
} }
...@@ -9118,7 +9114,7 @@ static int __Pyx_CyFunction_init(void) ...@@ -9118,7 +9114,7 @@ static int __Pyx_CyFunction_init(void)
__pyx_CyFunctionType = &__pyx_CyFunctionType_type; __pyx_CyFunctionType = &__pyx_CyFunctionType_type;
return 0; return 0;
} }
""" % Naming.__dict__) """)
generator_utility_code = UtilityCode( generator_utility_code = UtilityCode(
proto=""" proto="""
......
...@@ -39,6 +39,27 @@ def test_doc(): ...@@ -39,6 +39,27 @@ def test_doc():
'docstring' 'docstring'
""" """
def test_closure():
"""
>>> test_closure.func_closure is None
True
"""
def test_globals():
"""
>>> test_globals.func_globals is not None
True
>>> 'test_globals' in test_globals.func_globals or test_globals.func_globals
True
>>> 'test_name' in test_globals.func_globals or test_globals.func_globals
True
>>> 'not there' not in test_globals.func_globals or test_globals.func_globals
True
>>> try: test_globals.func_globals = {}
... except (AttributeError, TypeError): pass
... else: assert 0, 'FAILED'
"""
def test_reduce(): def test_reduce():
""" """
>>> import pickle >>> import pickle
......
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