Commit d831d71a authored by Matthias Braun's avatar Matthias Braun Committed by GitHub

Keep reference to module dict around also in limited mode (GH-3707)

`PyModule_GetDict` is part of the limited API so we can keep a reference
to the module dict around regardless of limited mode being enabled or not.
parent 30f616cd
......@@ -2349,12 +2349,6 @@ class NameNode(AtomicExprNode):
elif entry.scope.is_module_scope:
setter = 'PyDict_SetItem'
namespace = Naming.moddict_cname
code.putln("{")
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
# global module dict doesn't seems to exist in the limited API so create a temp variable
code.putln("PyObject *%s = PyModule_GetDict(%s); %s" % (
namespace, Naming.module_cname, code.error_goto_if_null(namespace, self.pos)))
code.putln("#endif")
elif entry.is_pyclass_attr:
# Special-case setting __new__
n = "SetNewInClass" if self.name == "__new__" else "SetNameInClass"
......@@ -2378,8 +2372,6 @@ class NameNode(AtomicExprNode):
# in Py2.6+, we need to invalidate the method cache
code.putln("PyType_Modified(%s);" %
entry.scope.parent_type.typeptr_cname)
elif entry.scope.is_module_scope:
code.putln("}")
else:
if self.type.is_memoryviewslice:
self.generate_acquire_memoryviewslice(rhs, code)
......@@ -9438,21 +9430,8 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
else:
flags = '0'
borrowed_moddict_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln('%s = PyModule_GetDict(%s); %s' % (
borrowed_moddict_temp,
Naming.module_cname,
code.error_goto_if_null(borrowed_moddict_temp, self.pos)))
code.putln("#else")
code.putln("%s = %s; if ((1)); else %s;" % (
borrowed_moddict_temp,
Naming.moddict_cname,
code.error_goto(self.pos),
))
code.putln("#endif")
code.putln(
'%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s = NULL; %s' % (
'%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % (
self.result(),
constructor,
self.pymethdef_cname,
......@@ -9460,11 +9439,9 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
self.get_py_qualified_name(code),
self.closure_result_code(),
self.get_py_mod_name(code),
borrowed_moddict_temp,
Naming.moddict_cname,
code_object_result,
borrowed_moddict_temp,
code.error_goto_if_null(self.result(), self.pos)))
code.funcstate.release_temp(borrowed_moddict_temp)
self.generate_gotref(code)
......
......@@ -2543,6 +2543,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# TODO: Reactor LIMITED_API struct decl closer to the static decl
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln('typedef struct {')
code.putln('PyObject *%s;' % env.module_dict_cname)
code.putln('PyObject *%s;' % Naming.builtins_cname)
code.putln('PyObject *%s;' % Naming.cython_runtime_cname)
code.putln('PyObject *%s;' % Naming.empty_tuple)
......@@ -2595,6 +2596,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_module_state_defines(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln('#define %s %s->%s' % (
env.module_dict_cname,
Naming.modulestateglobal_cname,
env.module_dict_cname))
code.putln('#define %s %s->%s' % (
Naming.builtins_cname,
Naming.modulestateglobal_cname,
......@@ -2640,6 +2645,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.modulestate_cname,
Naming.modulestate_cname))
code.putln("if (!clear_module_state) return 0;")
code.putln('Py_CLEAR(clear_module_state->%s);' %
env.module_dict_cname)
code.putln('Py_CLEAR(clear_module_state->%s);' %
Naming.builtins_cname)
code.putln('Py_CLEAR(clear_module_state->%s);' %
......@@ -2666,6 +2673,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.modulestate_cname,
Naming.modulestate_cname))
code.putln("if (!traverse_module_state) return 0;")
code.putln('Py_VISIT(traverse_module_state->%s);' %
env.module_dict_cname)
code.putln('Py_VISIT(traverse_module_state->%s);' %
Naming.builtins_cname)
code.putln('Py_VISIT(traverse_module_state->%s);' %
......@@ -2899,9 +2908,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for cname, type in code.funcstate.all_managed_temps():
code.put_xdecref(cname, type)
code.putln('if (%s) {' % env.module_cname)
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln('if (%s) {' % env.module_dict_cname)
code.putln("#endif")
code.put_add_traceback(EncodedString("init %s" % env.qualified_name))
code.globalstate.use_utility_code(Nodes.traceback_utility_code)
# Module reference and module dict are in global variables which might still be needed
......@@ -2909,8 +2916,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# At least clearing the module dict here might be a good idea, but could still break
# user code in atexit or other global registries.
##code.put_decref_clear(env.module_dict_cname, py_object_type, nanny=False)
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln('}')
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.put_decref_clear(env.module_cname, py_object_type, nanny=False, clear_before_decref=True)
code.putln("#endif")
code.putln('} else if (!PyErr_Occurred()) {')
......@@ -3135,9 +3142,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
nanny=False, clear_before_decref=True)
for cname in [Naming.cython_runtime_cname, Naming.builtins_cname]:
code.put_decref_clear(cname, py_object_type, nanny=False, clear_before_decref=True)
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.put_decref_clear(env.module_dict_cname, py_object_type, nanny=False, clear_before_decref=True)
code.putln("#endif")
def generate_main_method(self, env, code):
module_is_main = self.is_main_module_flag_cname()
......@@ -3277,13 +3282,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif")
code.putln("#endif") # CYTHON_PEP489_MULTI_PHASE_INIT
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln(
"%s = PyModule_GetDict(%s); %s" % (
env.module_dict_cname, env.module_cname,
code.error_goto_if_null(env.module_dict_cname, self.pos)))
code.put_incref(env.module_dict_cname, py_object_type, nanny=False)
code.putln("#endif")
code.putln(
'%s = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); %s' % (
......
......@@ -20,15 +20,7 @@ static PyObject* __Pyx_Globals(void); /*proto*/
// access requires a rewrite as a dedicated class.
static PyObject* __Pyx_Globals(void) {
PyObject *globals;
#if CYTHON_COMPILING_IN_LIMITED_API
globals = PyModule_GetDict($module_cname);
if (unlikely(!globals)) return NULL;
#else
globals = $moddict_cname;
#endif
Py_INCREF(globals);
return globals;
return __Pyx_NewRef($moddict_cname);
}
//////////////////// PyExecGlobals.proto ////////////////////
......@@ -36,17 +28,11 @@ static PyObject* __Pyx_Globals(void) {
static PyObject* __Pyx_PyExecGlobals(PyObject*);
//////////////////// PyExecGlobals ////////////////////
//@requires: Globals
//@substitute: naming
//@requires: PyExec
static PyObject* __Pyx_PyExecGlobals(PyObject* code) {
PyObject* result;
PyObject* globals = __Pyx_Globals();
if (unlikely(!globals))
return NULL;
result = __Pyx_PyExec2(code, globals);
Py_DECREF(globals);
return result;
return __Pyx_PyExec2(code, $moddict_cname);
}
//////////////////// PyExec.proto ////////////////////
......
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