EXTENDED_ARG_QUICK is a problematic opcode, and I think we should expose it less than we currently do. It is the only "quickened" opcode emitted by the compiler and found in code.co_code, which requires us to jump through strange hoops in several places (I'm looking at you, _PyOpcode_Original). Even weirder, it traces as EXTENDED_ARG at runtime.
- it's not documented anywhere in the
dis documentation
- it's not even a "real" opcode exposed by any of the helpers in the
opcode module (which still defines a misleadingly useless EXTENDED_ARG constant)
- it's less than
HAVE_ARGUMENT, even though it (obviously) uses its argument
- it's not understood by things like
stack_effect
Yet consumers of the bytecode must handle it correctly. We've already seen several bugs in CPython where we wrongly thought that we were handling extended arguments, and code that's been unchanged for years silently stopped working correctly. Let's avoid putting user code through the same pain.
I propose that we only emit the normal EXTENDED_ARG in the compiler, like we always have, and use _PyOpcode_Deopt everywhere that _PyOpcode_Original is being used now. We'll quicken EXTENDED_ARG to EXTENDED_ARG_QUICK just like all of the other *_QUICK opcode variants. No need to change the magic number or anything, since old code will continue to work fine. Although EXTENDED_ARG is in theory a tiny bit slower (it deopts the next opcode using _PyOpcode_Deopt), I doubt this is actually measurable.
Thoughts? I really think we should try to do this in 3.11, since it's a relatively simple change.
CC @markshannon, @sweeneyde, @pablogsal
EXTENDED_ARG_QUICKis a problematic opcode, and I think we should expose it less than we currently do. It is the only "quickened" opcode emitted by the compiler and found incode.co_code, which requires us to jump through strange hoops in several places (I'm looking at you,_PyOpcode_Original). Even weirder, it traces asEXTENDED_ARGat runtime.disdocumentationopcodemodule (which still defines a misleadingly uselessEXTENDED_ARGconstant)HAVE_ARGUMENT, even though it (obviously) uses its argumentstack_effectYet consumers of the bytecode must handle it correctly. We've already seen several bugs in CPython where we wrongly thought that we were handling extended arguments, and code that's been unchanged for years silently stopped working correctly. Let's avoid putting user code through the same pain.
I propose that we only emit the normal
EXTENDED_ARGin the compiler, like we always have, and use_PyOpcode_Deopteverywhere that_PyOpcode_Originalis being used now. We'll quickenEXTENDED_ARGtoEXTENDED_ARG_QUICKjust like all of the other*_QUICKopcode variants. No need to change the magic number or anything, since old code will continue to work fine. AlthoughEXTENDED_ARGis in theory a tiny bit slower (it deopts the next opcode using_PyOpcode_Deopt), I doubt this is actually measurable.Thoughts? I really think we should try to do this in 3.11, since it's a relatively simple change.
CC @markshannon, @sweeneyde, @pablogsal