Skip to content
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

GH-93143: Don't turn LOAD_FAST into LOAD_FAST_CHECK #99075

Merged
merged 6 commits into from
Nov 8, 2022

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Nov 3, 2022

The compiler's dataflow analysis for fast locals can be invalidated by jumps or deletions while tracing. When this happens, rather than changing co_code (which users assume to be constant) to use the less-efficient LOAD_FAST_CHECK everywhere, just display a RuntimeWarning and set any problematic locals to None instead.

@brandtbucher brandtbucher added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Nov 3, 2022
@brandtbucher brandtbucher self-assigned this Nov 3, 2022
@brandtbucher brandtbucher marked this pull request as ready for review November 3, 2022 20:04
@sweeneyde
Copy link
Member

I can look closer this evening, but mutating co_code is not ideal, so I think this is probably a good idea.

Lib/test/test_peepholer.py Outdated Show resolved Hide resolved
Objects/frameobject.c Outdated Show resolved Hide resolved
Objects/frameobject.c Outdated Show resolved Hide resolved
Objects/frameobject.c Outdated Show resolved Hide resolved
@markshannon
Copy link
Member

There are two cases when we need to set locals to None.

  1. Deletion of locals
  2. Jumping to arbitrary code

In the first case we can set the local to None and issue the warning cheaply and probably correctly. That's fine.

However when jumping, trying to decide which locals need to be set to None is going to be complex, expensive and error prone.
So I think we should go with @sweeneyde suggestion of setting all the undefined local variables to None.
Either don't issue any warning (as it might be confusing), or maybe issue a generic warning only if any locals were set to None.

@brandtbucher
Copy link
Member Author

I've updated the code to skip scanning the bytecode for LOAD_FAST. Any unbound locals will be assigned None on jumps, and (if so) a single RuntimeWarning will be issued for all of them.

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

👍
This feels safer and more robust than what we have now.

Lib/test/test_peepholer.py Show resolved Hide resolved
@@ -0,0 +1,4 @@
Rather than changing :attr:`~types.CodeType.co_code`, the interpreter will
now display a :exc:`RuntimeWarning` and assign :const:`None` to any fast
locals that are incorrectly left unbound after jumps or :keyword:`del`
Copy link
Member

Choose a reason for hiding this comment

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

There aren't necessarily incorrect, so maybe just "locals that are unbound after ..."

Objects/frameobject.c Show resolved Hide resolved
Objects/frameobject.c Show resolved Hide resolved
PyErr_WriteUnraisable((PyObject *)frame->frame_obj);
}
value = Py_NewRef(Py_None);
}
Py_XINCREF(value);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Py_XINCREF(value);
Py_INCREF(value);

@bedevere-bot
Copy link

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants