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:
Tian Gao 2023-11-03 09:39:50 -07:00 committed by GitHub
parent 2bc01cc0c7
commit e0afed7e27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 114 additions and 8 deletions

View file

@ -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);
}