mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-103615: Use local events for opcode tracing (GH-109472)
* Use local monitoring for opcode trace * Remove f_opcode_trace_set * Add test for setting f_trace_opcodes after settrace
This commit is contained in:
parent
2bc01cc0c7
commit
e0afed7e27
9 changed files with 114 additions and 8 deletions
|
@ -117,6 +117,35 @@ sys_profile_call_or_return(
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
_PyEval_SetOpcodeTrace(
|
||||
PyFrameObject *frame,
|
||||
bool enable
|
||||
) {
|
||||
assert(frame != NULL);
|
||||
assert(PyCode_Check(frame->f_frame->f_executable));
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *)frame->f_frame->f_executable;
|
||||
_PyMonitoringEventSet events = 0;
|
||||
|
||||
if (_PyMonitoring_GetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, &events) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (events & (1 << PY_MONITORING_EVENT_INSTRUCTION)) {
|
||||
return 0;
|
||||
}
|
||||
events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
|
||||
} else {
|
||||
if (!(events & (1 << PY_MONITORING_EVENT_INSTRUCTION))) {
|
||||
return 0;
|
||||
}
|
||||
events &= (~(1 << PY_MONITORING_EVENT_INSTRUCTION));
|
||||
}
|
||||
return _PyMonitoring_SetLocalEvents(code, PY_MONITORING_SYS_TRACE_ID, events);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
|
||||
{
|
||||
|
@ -130,6 +159,12 @@ call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
|
|||
"Missing frame when calling trace function.");
|
||||
return NULL;
|
||||
}
|
||||
if (frame->f_trace_opcodes) {
|
||||
if (_PyEval_SetOpcodeTrace(frame, true) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Py_INCREF(frame);
|
||||
int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg);
|
||||
Py_DECREF(frame);
|
||||
|
@ -230,11 +265,14 @@ sys_trace_instruction_func(
|
|||
"Missing frame when calling trace function.");
|
||||
return NULL;
|
||||
}
|
||||
if (!frame->f_trace_opcodes) {
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
if (!tstate->c_tracefunc || !frame->f_trace_opcodes) {
|
||||
if (_PyEval_SetOpcodeTrace(frame, false) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
Py_INCREF(frame);
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
|
||||
frame->f_lineno = 0;
|
||||
Py_DECREF(frame);
|
||||
|
@ -531,9 +569,15 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
|||
(1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) |
|
||||
(1 << PY_MONITORING_EVENT_STOP_ITERATION) |
|
||||
(1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED);
|
||||
if (tstate->interp->f_opcode_trace_set) {
|
||||
events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
|
||||
|
||||
PyFrameObject* frame = PyEval_GetFrame();
|
||||
if (frame->f_trace_opcodes) {
|
||||
int ret = _PyEval_SetOpcodeTrace(frame, true);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue