-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
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
[draft] register machine #100276
[draft] register machine #100276
Conversation
iritkatriel
commented
Dec 15, 2022
•
edited
Loading
edited
- Each instruction is written to the bytecode as two code units, one for opcode + oparg1, the second for oparg2 + oparg3. (oparg2,3 are 0 for now).
- Add a copy of the consts to the end of the fast locals array, which now consists of [localsplus, the stack, consts].
- Register versions of the UNARY_* ops, with tmp registers added to the localsplus as "$i".
I have a test failing (locally, will probably fail here too) due to the per-instruction stack depth calculating dipping below 0 (there's an assertion that it doesn't). I think it could be due to the stack effect of CALL being off by 1 - it depends on the value of is_meth which is not known to stack_effect(). |
That's not what it was - I saw a test pass the first time and then fail the stackdepth>0 assertion only second time I ran it. Now my local build is broken and nothing seems to help (I tried distclean/clean/touching all the stdlib/bumping magic number). |
209cf1a
to
e7bc5f2
Compare
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.
I found my first bug. :-)
The tests all pass on Mac now. On windows there's a problem with test_import's test_unencodable_filename, which runs in a subprocess. |
I can reproduce this on windows, it does: Fatal Python error: _Py_CheckSlotResult: Slot |= of type set failed without setting an exception I managed to get it to print: |
It enters set_ior with an exception set. I don't know if that's supposed to happen. |
I'm sure it's not supposed to. |
…ut let's see what this does to the buildbots)
Lib/test/test_patma.py
Outdated
@@ -2172,7 +2172,7 @@ def test_patma_204(self): | |||
def f(w): | |||
match w: | |||
case 42: | |||
out = locals() | |||
out = {k : v for k,v in locals().items() if not k.startswith('$')} |
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.
I wonder if the exception for $
should be implemented in locals()
rather than in its callers?
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.
I don’t know if we want to keep the $ vars. we did this because I couldn’t get it to work with a dedicated range for temps, but now we fixed it for consts so it should work.
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.
We might want these for debugging purposes. Perhaps locals
/frame.f_locals
should omit them, and we add frame._f_registers
(or something) which is a list of temporaries?
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.
Maybe relevant: the unnamed iterator used in comprehensions is currently visible:
>>> [locals() for _ in [None]]
[{'.0': <tuple_iterator object at 0x7f1a741370a0>, '_': None}]
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.
The $
registers will be visible in a lot more cases than the .0
iterator, and they are a detail of the implementation that will mostly just confuse users. If we're going to pull the consistency card I'd vote for not revealing that iterator either.
I could live with the registers showing in f_locals
but not in locals()
-- frame attributes are more of an implementation detail anyway.
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.
I made the change to filter locals(), but that's no good it breaks locals()["x"] = 43
.
(see test.test_scope.ScopeTests.testClassNamespaceOverridesClosure)
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.
Why are we adding all these "$" variables to the locals?
We don't expose the stack, why expose the temporaries?
It looks like a considerable amount of the changes to both code and tests are supporting/working around these additional, artificial local variables.
This currently becomes the code below (CALL is not a register op yet). I got this with simple peephole style cleanup of the registers (we could probably still reduce the number of register used, my peephole is just about eliminating LOAD/STORE/COPY instructions). I think this could end up being a simpler approach than re-architecting the code-gen visitors to pass inputs and outputs up and down the recursion.
|
To summarise today's adventures: When can optimize away a STORE_FAST_R whose target is a tmp, but not a local. My last commit did this, but I reverted it because it has issues with refcounts. Basically, a COPY_R does an INCREF, and when we optimise one away we lose a reference, so this also needs to be done selectively. I'll figure out when it does or doesn't work tomorrow. |
Starting again at #101078. |