-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
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
Bytecode documentation issues for Python 3.12 #107457
Comments
@MatthieuDartiailh Thanks for this. Are you working on a PR? |
Not at the moment. If I manage to finish my work on bytecode, I will make a PR, but feel free to beat me to it. |
Also note that while I could address many of those, I did not figure out yet what the lower 4 bits of COMPARE_OP are for. |
See this fragment from Include/internal/pycore_code.h:
|
Thanks ! I also found this fragment in compile.c that completes the picture: static const int compare_masks[] = {
[Py_LT] = COMPARISON_LESS_THAN,
[Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS,
[Py_EQ] = COMPARISON_EQUALS,
[Py_NE] = COMPARISON_NOT_EQUALS,
[Py_GT] = COMPARISON_GREATER_THAN,
[Py_GE] = COMPARISON_GREATER_THAN | COMPARISON_EQUALS,
}; |
Thanks for the report!
Re-reading this doc entry, I think it could be clearer that it pops three elements from the stack and pushes either one or two, depending on low bit of oparg (just like I'm not convinced that a code block would be better than a small addition to the prose. A code block is more verbose and introduces more distracting details, which would either be confusing because they differ from the actual implementation, or confusing because they match the actual implementation and thus add complexity that isn't needed in the documentation. But if you have an example of what a code block clarification would look like that you think is better than prose, I'm open to considering it. |
Not to mention this magical code in bytecodes.c:
and
That completes the picture; these are the only two uses (but they are in very performance-critical code, hence all these shenanigans). |
I just noticed that |
If anybody could enlighten me regarding the use of END_SEND and CLEANUP_THROW I would greatly appreciate it. I am currently having some issues when trying to compute the stack size for async function using |
It seems to me that
Which to me sounds like two values are removed from the stack and one is pushed giving a stack of -1 but Another undocumented feature if that when jumping the offset is augmented by 1 compared to the oparg !!! which is rather surprising. EDIT: same issue for FOR_ITER |
For SEND, comparing the description to the actual code in the main branch, it looks like the docs are just wrong -- it leaves STACK[-2] (the generator or generator-ish object) in place. According to blame, that sentence was originally written by @brandtbucher about a year ago -- maybe it was always wrong, or maybe the implementation of SEND has changed since then? (The new sentence doesn't appear in the 3.11 docs, only in 3.12 and 3.13.) I'm not sure the FOR_ITER docs are incorrect -- it doesn't have the same sentence in its docs, nor are the semantics the same. It's clear in main that it pushes an extra value if |
Thanks for your confirmation for the Regarding See for example:
to reach the same conclusion as dis, one needs to know the oparg is augmented by one. |
If you ask
That's in main; in 3.12, This should be the same as for other forward jumps. |
My issue is that it is not the same for other jump forward instr. In the above example from @gvanrossum , we start counting from the instruction at offset 26, and we count 3 instructions: the one at offset 28, 30 and 32 but
To figure out the target of Does my explanation make sense ? |
Different issue: |
The question to ask generally is, where would a jump with oparg == 0 go. It should always go to the instruction immediately following the jump, after any caches belonging to the jump have been accounted for. (Also, the count isn't really instructions -- an instruction can include cache entries so it has a variable length. The jump count is a number of "instruction units", which are always 2 bytes.) |
IIRC co_fastlocalnames got renamed when we unified the numbering for locals and fast locals. I think we're looking for co_localsplusnames now. (In 3.13, LOAD_CLOSURE is gone.) |
Thanks for the explanation regarding the jumps. It turns what looked like a magic number for just two opcodes into a generic rule. Would it be fine to add this explanation to the dis documentation ? |
That would be great! |
…nGH-108900) (cherry picked from commit 198aa67) Co-authored-by: Matthieu Dartiailh <[email protected]>
I believe all points have been addressed by the referenced PRs and this can now be closed. |
As part of adding support for Python 3.12 to https://github.com/MatthieuDartiailh/bytecode I have identified a number of documentation issues both in the
dis
module documentation in the bytecode section of theWhat's new in 3.12
. Opening a separate issue for each point would just clutter the issue tracker so I will try to summarize all my findings here.Issue in
dis
documentationThe operation name can be found in cmp_op[opname]
is not true anymore.dis.dis
outputMIN_INSTRUMENTED_OPCODE
is not documented but needed to determine what are the "normal" opcodesLOAD_SUPER_ATTR
description could use a code block to describe its stack effect IMOPOP_JUMP_IF_NOT_NONE
andPOP_JUMP_IF_NONE
are still described as pseudo-instructions even though there are not anymore in 3.12CALL_INSTRINSIC_2
stack manipulation description looks wrong.The description reads
Passes STACK[-2], STACK[-1] as the arguments and sets STACK[-1] to the result
, but the implementation pops 2 values from the stackEND_SEND
is not documentedCACHE
instructions following jumping instructions is not described (FOR_ITER and SEND for the time being)Issue in What's new
BINARY_SLICE
is not mentionedSTORE_SLICE
is not mentionedCLEANUP_THROW
is not mentionedRETURN_CONST
is not mentionedLOAD_FAST_CHECK
is not mentionedEND_SEND
is not mentionedCALL_INSTRINSIC_1/2
are not mentionedFOR_ITER
new behavior is not mentionedPOP_JUMP_IF_*
family of instructions are now real instructions is not mentionedYIELD_VALUE
need for an argument is not mentioneddis.hasexc
is not mentionedLinked PRs
The text was updated successfully, but these errors were encountered: