-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-43693: Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. #26388
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
bpo-43693: Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. #26388
Conversation
af397af
to
fda53f1
Compare
c95f4cc
to
0d1d6cd
Compare
Some thoughts on the API. I don't like the word "fast". It has no meaning and just makes names longer. I'd much prefer "variables" to "fastlocals". So I was thinking... class CodeType:
def get_variable_name(self, n:int):
"Return the names of the nth variable"
def get_variable_scope(self, n:int):
"Returns the scope of the nth var (one of LOCAL, ESCAPES, FREE)"
def get_variable_kind(self, n:int):
"Return the kind of nth var (one of LOCAL, ARG, VARARG, etc)" or class CodeType:
def get_variable_metadata(self, n:int):
"Returns a triple (name, scope, kind) for nth variable" What do you think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple drive-by comments.
Yeah, they were fast several decades ago when this was an improvement over storing locals in a dict. :-) But it's a traditional name, and changing it would just add a bunch of additional unneeded churn (e.g. we have LOAD_FAST etc. -- to be consistent you'd have to rename those too). Plus, these locals really are pretty fast. :-) [...]
At least some debuggers access this data in C, so we'd have to introduce C API functions as well. I don't think we'll actually be able to come up with abstractions that won't have to change if this stuff changes again in the future. I think that at least for this PR, we should leave well enough alone -- at some point in the future, |
If the abstraction models the language, then it shouldn't need to change (unless the language does). The scope (local, escapes, or free), the kind (arg, kwarg, non-arg, etc), and the name are all properties of the variable and independent of the data structures used. |
Yeah, let's make sure to settle this API once we're farther along, but
within the 3.11 timeframe.
|
Why not do it now? What is the advantage of exposing things to hide them later. |
I'm fine with taking a more neutral approach, along the lines you suggested. However, I don't want to introduce a new public API (in Python or in C) in this PR. |
@markshannon, please take another look at this PR when you get the chance. |
Windows warnings need fixing: https://github.com/python/cpython/pull/26388/files#diff-ebc983d9f91e5bcf73500e377ac65e85863c4f77fd5b6b6caf4fcdf7c0f0b057R7253 You say that you don't want to add a public API, but that is what you are doing by adding |
You mean the fields on the struct? I was talking about the attributes exposed to Python code. As far as the struct goes, I'm fine with adding an underscore prefix but I don't see the point since using the fields is required and given the class of expected users. I'd rather make In the meantime I will add an undercore prefix to those fields so we can move this along. |
I meant the Python attributes, but it looks like you've already removed them 👍 |
9dcd35d
to
fdf040a
Compare
fdf040a
to
87cb192
Compare
Thanks, @markshannon! |
…names and co_fastlocalkinds. (pythongh-26388)" This reverts commit 2c1e258.
These were reverted in pythonGH-26530 (commit 17c4edc). * Compute deref offsets in compiler (pythongh-25152) * Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. (pythongh-26388)
These were reverted in gh-26530 (commit 17c4edc) due to refleaks. * 2c1e258 - Compute deref offsets in compiler (gh-25152) * b2bf2bc - Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. (gh-26388) This change fixes the refleaks. https://bugs.python.org/issue43693
A number of places in the code base (notably ceval.c and frameobject.c) rely on mapping variable names to indices in the frame "locals plus" array (AKA fast locals), and thus opargs. Currently the compiler indirectly encodes that information on the code object as the tuples
co_varnames
,co_cellvars
, andco_freevars
. At runtime the dependent code must calculate the proper mapping from those, which isn't ideal and impacts performance-sensitive sections. This is something we can easily address in the compiler instead.This PR addresses the situation by replacing internal use of
co_varnames
, etc. with a single combined tuple of names in locals-plus order, along with a minimal array mapping each to its kind (local vs. cell vs. free). These two newPyCodeObject
fields,co_fastlocalnames
andco_fastllocalkinds
, are not exposed to Python code for now, butco_varnames
, etc. are still available with the same values as before (though computed lazily).Aside from the (mild) performance impact, there are a number of other benefits:
Also note that we can take this approach further by expanding the possible values in
co_fastlocalkinds
to include specific argument types (e.g. positional-only, kwargs). Doing so would allow further speed-ups in_PyEval_MakeFrameVector()
, which is where args get unpacked into the locals-plus array. It would also allow us to shrink marshaled code objects even further.(FYI, I have a later PR that relies on having this direct mapping instead of
co_varnames
.)FWIW, if this PR is too big I can split it up between "add the fields" and "use the fields". However, typically in this project we keep those together in one change.
https://bugs.python.org/issue43693