Repository navigation
Decoding instructions should handle ENTER_EXECUTOR #107265
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Jul 25, 2023 Open question. Should
ENTER_EXECUTORbe replaced by_Py_GetBaseOpcode()or is that its caller's responsibility? Indeopt_code()the caller handles it, but in other cases the caller doesn't, but (probably) should. But you could also argue that the fix is to switch to using_PyInstruction_GetLength()instead of1 + _PyOpcode_Caches[opcode].@markshannon Do you have an opinion?
I am working on
code_hashtooReacted by Guido van Rossum- added 4 commits that reference this issue
on Aug 21, 2023 Ideally, everything would use the same set of functions to get instruction lengths, opcodes and opargs.
The interaction between instrumentation and
ENTER_EXECUTORis more than just theENTER_EXECUTORitself, as we need to invalidate any executor if any of the instructions that it covers is instrumented.I think we can remove
_PyFrame_OpAlreadyRanaltogether. If not now, definitely when PEP 667 is implemented.Reacted by Donghee NaI think we can remove
_PyFrame_OpAlreadyRanaltogether. If not now, definitely when PEP 667 is implemented.But PEP 667 seems in limbo (and rather ambitious, so I wouldn't want to wait for it if we can drop
_PyFrame_OpAlreadyRan).I don't understand at all what
_PyFrame_OpAlreadyRandoes or why, or if there's a test for it. I addedassert(check_opcode != ENTER_EXECUTOR);to it and am now running the test suite with
-Xuopsalways on; we'll see in about an hour how that goes. (Hum, well, if at least one standard CI job runs runs with assertions enabled.)So the entire test suite run with
-Xuopshard-coded and a hard-coded check in_PyFrame_OpAlreadyRanthatcheck_opcode != ENTER_EXECUTORfound nothing, so maybe there's some good reason why that function isn't a problem. In any case it's not a priority.Guido, IIUC, we don't need to fix
de_instrument.
Becausede_instrumentis only called fromremovetoolsand it requires that opcode should have event.
I will send a PR to add one line of assert statement for the context.Please let me know if I miss something.
cpython/Python/instrumentation.c
Lines 705 to 727 in 154477b
static void remove_tools(PyCodeObject * code, int offset, int event, int tools) { assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); assert(opcode_has_event(_Py_GetBaseOpcode(code, offset))); _PyCoMonitoringData *monitoring = code->_co_monitoring; if (monitoring && monitoring->tools) { monitoring->tools[offset] &= ~tools; if (monitoring->tools[offset] == 0) { de_instrument(code, offset, event); } } else { /* Single tool */ uint8_t single_tool = code->_co_monitoring->active_monitors.tools[event]; assert(_Py_popcount32(single_tool) <= 1); if (((single_tool & tools) == single_tool)) { de_instrument(code, offset, event); } } } cpython/Python/instrumentation.c
Lines 121 to 127 in 154477b
opcode_has_event(int opcode) { return ( opcode != INSTRUMENTED_LINE && INSTRUMENTED_OPCODES[opcode] > 0 ); } 14 remaining items
- added 6 commits that reference this issue
on Aug 27, 2023 About
_PyFrame_OpAlreadyRanwe don't have to do anything if it is removed: faster-cpython/ideas#623 (comment)- added a commit that references this issue
on Sep 22, 2023 - addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Nov 28, 2023 PEP 667 landed for 3.13, and a code search indicates
_PyFrame_OpAlreadyRanis gone, so is there anything left to resolve for this issue?(This issue came up while doing a search for "PEP 667" to check for issues that could be closed now that has been implemented)
We now have
_Py_GetBaseCodeUnitwhich returns the underlying code unit, handling instrumentation andENTER_EXECUTOR, and is used in (almost?) all places it is needed.
There's a variety of places where we walk over an array of instructions, using some variant of
All these make the mistake that if
opcodeisENTER_EXECUTOR, it may obscure an underlyingJUMP_BACKWARDinstruction, which has a cache entry.I fixed this in gh-107256 for
_PyInstruction_GetLength()and it was first reported in gh-107082, but there are a number of other occurrences. Basically every time we consult_PyOpcode_Cacheswe should ensure that the index is notENTER_EXECUTOR.CC: @markshannon
Places where I found this:
_Py_GetBaseOpcode[should not be "fixed", it would break callers that need the oparg]There are possibly others.
Linked PRs