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