-
Notifications
You must be signed in to change notification settings - Fork 50
Single instruction "superinstructions" #585
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
Comments
Just a note from our previous discussions for anyone else reading: this is only legal if both instructions are on the same line. When I tried a similar idea out before, this caused almost all of the |
Instructions don't really have lines, effects do. Since a = 1
return b which compiles to:
Which implies that we cannot merge the
Which can be transformed to:
|
Unfortunately, having superinstructions straddling lines prevents jumping to the line in question in a debugger, as the stack is inconsistent, which rules out the transformation above. However, it appears that the reduction in code size more than compensates. |
Does this mean that in general we have to consider the state of the value stack as an "observable side effect" when making optimizations in the compiler? That seems new (relative to my previous understanding of what was safe to optimize), and unfortunate. |
Well, I would assume that jumping to a line would jump just prior to execution of every instruction on that line. It would be weird, I think, if a local variable load or store didn't happen after jumping to a line and and stepping through it. |
In the example above, I would expect that if I had two lines |
I'm not proposing anything in particular; It seems this does mean that |
Lucky! ;) |
Do we know anyone who uses this evil function? |
Here's a third-party debugger that uses it: https://github.com/web2py/web2py/blob/7685d373474378e93132f8916145fb11f84cec71/gluon/contrib/dbg.py#L307. pdb also supports it (https://github.com/python/cpython/blob/e01b04c9075c6468ed57bc883693ec2a06a6dd8e/Lib/pdb.py#L1202). Seems like we should seriously consider deprecating support for this feature though; it feels very rarely useful and very hard to support. |
I mean, I'm pretty sure every Python debugger has a If we convinced them to drop the functionality too, then maybe we'd find out how many users are really relying on it. There are at least a handful that have filed various bug reports for CPython over the years. I'm stuck somewhere between "I can see how it could be useful" and "it's too much pain to maintain and doesn't always work"... though, I have admittedly used |
I know debuggers support it. But do we know of any people who use it? |
Not counting people who use the feature via debuggers? I mean, you can only do it from within a trace function, so probably just a handful of people writing toys like this: import sys
def goto(line: int) -> None:
def jumper(frame, event, arg) -> None:
if event == "line":
frame.f_lineno = line
frame.f_trace = None
frame = sys._getframe(1)
frame.f_trace = jumper
sys.settrace(jumper)
# Prints "B" in an infinite loop:
goto(15) # 13
print("A") # 14
print("B") # 15
goto(13) # 16
print("C") # 17 |
There are already many complicated prohibitions in the Additionally, stepping through code already frequently jumps back and forth in ways that are hard to grasp intuitively. Again, if optimizations cause the sequence of observed "line events" to change, that feels like a minor inconvenience at best. (And even though PEP 626 claims otherwise, its motivation feels arbitrary to me and its specification is rather vague: "Line events and the |
Let's not remove jumping in debuggers, or other features, that make our work more Many features that prevent optimizations in the bytecode compiler can be handled in the tier 1 optimizer. |
Superinstructions can be problematic, as they break the one-instruction-at-a-time model that instrumentation relies on, and are likely to cause problems in optimizers that make the same one-instruction-at-a-time assumption.
Instrumentation rewrites all superinstructions back to the simpler form.
Super instructions also prevent specialization, so superinstructions cannot include any specializable instruction.
#584 proposes a specialization of
LOAD_CONST
, so that leaves onlyLOAD_FAST
andSTORE_FAST
to be combined.If we remove
LOAD_CONST
we have only:That is still quite a lot of instructions, dynamically, so we don't want to just remove them.
Instead of removing them, we can combine them into a single instruction.
Given that most locals will have a index in
range(16)
we combine the operations into a single instruction.There will be fewer
LOAD_FAST_LOAD_FAST_COMPACT
thanLOAD_FAST__LOAD_FAST
, but they should be a little faster (fewer memory reads). I would expect the performance to be about the same.The text was updated successfully, but these errors were encountered: