Skip to content

[mypyc] Add cleanup at end of init function #10590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 13, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions mypyc/codegen/emitmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
declaration = 'PyObject *CPyInit_{}(void)'.format(exported_name(module_name))
emitter.emit_lines(declaration,
'{')
emitter.emit_line('PyObject* modname = NULL;')
# Store the module reference in a static and return it when necessary.
# This is separate from the *global* reference to the module that will
# be populated when it is imported by a compiled module. We want that
Expand All @@ -890,7 +891,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
'if (unlikely({} == NULL))'.format(module_static),
' goto fail;')
emitter.emit_line(
'PyObject *modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format(
'modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format(
module_static))

module_globals = emitter.static_name('globals', module_name)
Expand All @@ -899,9 +900,11 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module
' goto fail;')

# HACK: Manually instantiate generated classes here
type_structs = [] # type: List[str]
for cl in module.classes:
type_struct = emitter.type_struct_name(cl)
type_structs.append(type_struct)
if cl.is_generated:
type_struct = emitter.type_struct_name(cl)
emitter.emit_lines(
'{t} = (PyTypeObject *)CPyType_FromTemplate('
'(PyObject *){t}_template, NULL, modname);'
Expand All @@ -918,8 +921,18 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module

emitter.emit_line('return {};'.format(module_static))
emitter.emit_lines('fail:',
'{} = NULL;'.format(module_static),
'return NULL;')
'Py_CLEAR({});'.format(module_static),
'Py_CLEAR(modname);')
for name, typ in module.final_names:
static_name = emitter.static_name(name, module_name)
emitter.emit_dec_ref(static_name, typ, is_xdec=True)
undef = emitter.c_undefined_value(typ)
emitter.emit_line('{} = {};'.format(static_name, undef))
# the type objects returned from CPyType_FromTemplate are all new references
# so we have to decref them
for t in type_structs:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also do the finals, too. Those need to be reset to whatever the proper error value for the type is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you take a look at ea8b1b2? I added clean up for some finals but I think there are some types that we should clean up which that doesn't cover.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the right thing to do is to call out to emit_dec_ref, which knows how to decref everything: https://github.com/python/mypy/blob/master/mypyc/codegen/emit.py#L344

And then assign the result of c_undefined_value to the variable, to clear it out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that does look a lot cleaner. This should be fixed in ebe20ed.

emitter.emit_line('Py_CLEAR({});'.format(t))
emitter.emit_line('return NULL;')
emitter.emit_line('}')

def generate_top_level_call(self, module: ModuleIR, emitter: Emitter) -> None:
Expand Down