From b2d19c391fc48ff4b82834a1fb5b9e3bc20fa641 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 14:10:30 +0000 Subject: [PATCH 01/79] gh-111997: C-API for signalling monitoring events --- Include/internal/pycore_instruments.h | 83 +++++++ Modules/Setup.stdlib.in | 2 +- Modules/_testinternalcapi.c | 3 + Modules/_testinternalcapi/monitoring.c | 304 +++++++++++++++++++++++++ Modules/_testinternalcapi/parts.h | 1 + Python/instrumentation.c | 273 ++++++++++++++++++++++ 6 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 Modules/_testinternalcapi/monitoring.c diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index eae8371ef7f9b8..b9a7dc05e45da9 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -101,6 +101,89 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index); extern PyObject _PyInstrumentation_MISSING; extern PyObject _PyInstrumentation_DISABLE; +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + + +/*** C API ***/ + +PyAPI_FUNC(void) +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + + +PyAPI_FUNC(int) +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); + +PyAPI_FUNC(int) +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + + +PyAPI_FUNC(int) +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +PyAPI_FUNC(int) +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +PyAPI_FUNC(int) +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + #ifdef __cplusplus } #endif diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 73b082691a3fd4..958583e66109b5 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -161,7 +161,7 @@ @MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c -@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/monitoring.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/hash.c _testcapi/time.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index db8817418950b9..4a04cbf63959f4 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1769,6 +1769,9 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } + if (_PyTestInternalCapi_Init_Monitoring(module) < 0) { + return 1; + } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c new file mode 100644 index 00000000000000..800c4b9e46a6c1 --- /dev/null +++ b/Modules/_testinternalcapi/monitoring.c @@ -0,0 +1,304 @@ +#include "parts.h" +#include "../_testcapi/util.h" // NULLABLE, RETURN_INT + +#include "pycore_instruments.h" + + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyStartEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_py_resume(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyResumeEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval)); +} + +static PyObject * +fire_event_py_yield(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + return NULL; + } + NULLABLE(codelike); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); +} + +static PyObject * +fire_event_py_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyCallEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_line(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *lineno; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { + return NULL; + } + NULLABLE(lineno); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); +} + +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireInstructionEvent(&state, codelike, offset)); +} + +static PyObject * +fire_event_jump(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset)); +} + +static PyObject * +fire_event_branch(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + return NULL; + } + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); +} + +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCReturnEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_py_throw(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_reraise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_exception_handled(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + return NULL; + } + NULLABLE(callable); + NULLABLE(arg0); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireCRaiseEvent(&state, codelike, offset, callable, arg0)); +} + +static PyObject * +fire_event_py_unwind(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception)); +} + +static PyObject * +fire_event_stop_iteration(PyObject *self, PyObject *args) +{ + PyObject *codelike; + uint32_t offset; + uint8_t active; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + return NULL; + } + NULLABLE(exception); + PyMonitoringState state = {active, 0}; + RETURN_INT(_PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception)); +} + +static PyMethodDef TestMethods[] = { + {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, + {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, + {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, + {"fire_event_py_call", fire_event_py_call, METH_VARARGS}, + {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_line", fire_event_line, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, + {"fire_event_jump", fire_event_jump, METH_VARARGS}, + {"fire_event_branch", fire_event_branch, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, + {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, + {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, + {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, + {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, + {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestInternalCapi_Init_Monitoring(PyObject *m) +{ + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index 49a1395f499fc3..f8a8ab695ee145 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -14,5 +14,6 @@ int _PyTestInternalCapi_Init_Lock(PyObject *module); int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); +int _PyTestInternalCapi_Init_Monitoring(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 6f1bc2e0a107df..e3b99e0d2e720f 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2276,3 +2276,276 @@ PyObject *_Py_CreateMonitoringObject(void) Py_DECREF(mod); return NULL; } + + +static int +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject **args, Py_ssize_t nargs, int event) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyInterpreterState *interp = tstate->interp; + + uint8_t tools = state->active; + assert(args[1] == NULL); + args[1] = codelike; + PyObject *offset_obj = PyLong_FromLong(offset); + if (offset_obj == NULL) { + return -1; + } + assert(args[2] == NULL); + args[2] = offset_obj; + Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET; + PyObject **callargs = &args[1]; + int err = 0; + + while (tools) { + int tool = most_significant_bit(tools); + assert(tool >= 0 && tool < 8); + assert(tools & (1 << tool)); + tools ^= (1 << tool); + int res = call_one_instrument(interp, tstate, callargs, nargsf, tool, event); + if (res == 0) { + /* Nothing to do */ + } + else if (res < 0) { + /* error */ + err = -1; + break; + } + else { + /* DISABLE */ + if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + PyErr_Format(PyExc_ValueError, + "Cannot disable %s events. Callback removed.", + event_names[event]); + /* Clear tool to prevent infinite loop */ + Py_CLEAR(interp->monitoring_callables[tool][event]); + err = -1; + break; + } + else { + state->opaque &= ~(1 << tool); + } + } + } + return err; +} + +void +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ +} + +int +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_PY_START); +} + +int +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_PY_RESUME); +} + +int +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* retval) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { retval, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_RETURN); +} + +int +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* retval) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { retval, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_YIELD); +} + +int +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_CALL); +} + +int +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_CALL); +} + +int +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { lineno, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_LINE); +} + +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[3] = { NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_INSTRUCTION); +} + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_JUMP); +} + +int +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_BRANCH); +} + +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_C_RETURN); +} + +int +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); +} + +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RAISE); +} + +int +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RERAISE); +} + +int +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_EXCEPTION_HANDLED); +} + +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + if (!state->active) { + return 0; + } + PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 4, + PY_MONITORING_EVENT_C_RAISE); +} + +int +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_UNWIND); +} + +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + if (!state->active) { + return 0; + } + PyObject *args[4] = { exception, NULL, NULL, NULL }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_STOP_ITERATION); +} From 1b9487c752601ff77aab9c1365bff9956406c44e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 21:58:13 +0000 Subject: [PATCH 02/79] remove unnecessary events and add a basic test --- Lib/test/test_monitoring.py | 60 ++++++++++++++++++++ Modules/_testinternalcapi/monitoring.c | 77 ++------------------------ Python/instrumentation.c | 72 +++++------------------- 3 files changed, 79 insertions(+), 130 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index b02795903f6d17..f6a1eabc76f058 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,6 +9,7 @@ import types import unittest import asyncio +import _testinternalcapi from test.support import requires_specialization PAIR = (0,1) @@ -1858,3 +1859,62 @@ def test_func(recorder): sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) sys.monitoring.set_events(TEST_TOOL, 0) self.assertGreater(len(events), 250) + + +class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): + + def setUp(self): + super(TestCApiEventGeneration, self).setUp() + + def cb(*args): + self.results.append(('cb',) + args) + + def cb2(*args): + self.results.append(('cb2',) + args) + + self.cb = cb + self.cb2 = cb2 + + events = sys.monitoring.events + capi = _testinternalcapi + self.cases = [ + # (Event, function, *args) + (events.PY_START, capi.fire_event_py_start), + (events.PY_RESUME, capi.fire_event_py_resume), + (events.PY_RETURN, capi.fire_event_py_return, 10), + (events.PY_YIELD, capi.fire_event_py_yield, 20), + (events.CALL, capi.fire_event_call, callable, 30), + (events.LINE, capi.fire_event_line, 40), + (events.JUMP, capi.fire_event_jump, 50), + (events.BRANCH, capi.fire_event_branch, 60), + (events.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + (events.RAISE, capi.fire_event_raise, ValueError(2)), + (events.RERAISE, capi.fire_event_reraise, ValueError(3)), + (events.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), + (events.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), + (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + ] + + def do_test(self, event, expected): + + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) + active = 1 << TEST_TOOL + + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + + self.assertEqual(self.results, [('cb',) + expected]) + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) + + def test_fire_event_py_start(self): + for offset, (event, function, *args) in enumerate(self.cases): + with self.subTest(event): + output = (function.__name__, offset, *args) + self.do_test(event, output) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 800c4b9e46a6c1..5b3ce297d7ad05 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -62,22 +62,6 @@ fire_event_py_yield(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); } -static PyObject * -fire_event_py_call(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyCallEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_call(PyObject *self, PyObject *args) { @@ -109,19 +93,6 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); } -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { - return NULL; - } - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireInstructionEvent(&state, codelike, offset)); -} - static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -150,22 +121,6 @@ fire_event_branch(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); } -static PyObject * -fire_event_c_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCReturnEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { @@ -173,7 +128,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -188,7 +143,7 @@ fire_event_raise(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -203,7 +158,7 @@ fire_event_reraise(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -218,7 +173,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -226,22 +181,6 @@ fire_event_exception_handled(PyObject *self, PyObject *args) RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); } -static PyObject * -fire_event_c_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - uint32_t offset; - uint8_t active; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { - return NULL; - } - NULLABLE(callable); - NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCRaiseEvent(&state, codelike, offset, callable, arg0)); -} - static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { @@ -249,7 +188,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -264,7 +203,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) uint32_t offset; uint8_t active; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; } NULLABLE(exception); @@ -277,18 +216,14 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, - {"fire_event_py_call", fire_event_py_call, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, - {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, {"fire_event_raise", fire_event_raise, METH_VARARGS}, {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, - {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, {NULL}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index e3b99e0d2e720f..7f0b7f0e248c4b 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2286,6 +2286,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t PyInterpreterState *interp = tstate->interp; uint8_t tools = state->active; +if (args[1]) _PyObject_Dump(args[1]); assert(args[1] == NULL); args[1] = codelike; PyObject *offset_obj = PyLong_FromLong(offset); @@ -2366,7 +2367,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, ui if (!state->active) { return 0; } - PyObject *args[4] = { retval, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_RETURN); } @@ -2378,23 +2379,11 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { retval, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_YIELD); } -int -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_CALL); -} - int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) @@ -2402,7 +2391,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; + PyObject *args[5] = { NULL, NULL, NULL, callable, arg0 }; return capi_call_instrumentation(state, codelike, offset, args, 4, PY_MONITORING_EVENT_CALL); } @@ -2414,22 +2403,11 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[4] = { lineno, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, lineno }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_LINE); } -int -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) -{ - if (!state->active) { - return 0; - } - PyObject *args[3] = { NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 2, - PY_MONITORING_EVENT_INSTRUCTION); -} - int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) @@ -2437,7 +2415,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32 if (!state->active) { return 0; } - PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_JUMP); } @@ -2449,23 +2427,11 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint if (!state->active) { return 0; } - PyObject *args[4] = { target_offset, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_BRANCH); } -int -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_C_RETURN); -} - int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) @@ -2473,7 +2439,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_THROW); } @@ -2485,7 +2451,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); } @@ -2497,7 +2463,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uin if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); } @@ -2509,23 +2475,11 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); } -int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0) -{ - if (!state->active) { - return 0; - } - PyObject *args[5] = { callable, arg0, NULL, NULL, NULL }; - return capi_call_instrumentation(state, codelike, offset, args, 4, - PY_MONITORING_EVENT_C_RAISE); -} - int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) @@ -2533,7 +2487,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, ui if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); } @@ -2545,7 +2499,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik if (!state->active) { return 0; } - PyObject *args[4] = { exception, NULL, NULL, NULL }; + PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } From 150011a08633e8feb2d526189ff1e6b1f74a4161 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 6 Mar 2024 22:56:23 +0000 Subject: [PATCH 03/79] enhance test --- Lib/test/test_monitoring.py | 60 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index f6a1eabc76f058..86fb0c260d61ee 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1895,26 +1895,52 @@ def cb2(*args): (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), ] - def do_test(self, event, expected): - - self.results = [] - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb) - sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) - active = 1 << TEST_TOOL + def test_fire_event(self): + for offset, (event, function, *args) in enumerate(self.cases): + with self.subTest(event): + output = (function.__name__, offset, *args) + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) + active = 1 << TEST_TOOL - try: - # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) - self.assertEqual(self.results, [('cb',) + expected]) - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) + self.assertEqual(self.results, [('cb',) + output]) + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) - def test_fire_event_py_start(self): + @unittest.skip("disable not implemented yet") + def test_disable_event(self): for offset, (event, function, *args) in enumerate(self.cases): with self.subTest(event): output = (function.__name__, offset, *args) - self.do_test(event, output) + self.results = [] + # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL + def cb(*args): + self.cb(*args) + return sys.monitoring.DISABLE + + sys.monitoring.register_callback(TEST_TOOL, event, cb) + active = 1 << TEST_TOOL + + try: + # fire one of each event type + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + self.assertEqual(self.results, [('cb',) + output]) + + # fire again - callbacks should be disabled now + self.results = [] + for offset, (_, function, *args) in enumerate(self.cases): + function(function.__name__, offset, active, *args) + self.assertEqual(self.results, []) + + finally: + sys.monitoring.register_callback(TEST_TOOL, event, None) + sys.monitoring.register_callback(TEST_TOOL2, event, None) From ebc36b5915da6b380fdff7fff9fb70cced0cbb75 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 13:48:25 +0000 Subject: [PATCH 04/79] enable disable tests. api test functions return the new 'active' value --- Lib/test/test_monitoring.py | 40 +++++++++++++----------- Modules/_testinternalcapi/monitoring.c | 42 +++++++++++++++++--------- Python/instrumentation.c | 5 ++- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 86fb0c260d61ee..87ad0903d058fa 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1899,47 +1899,51 @@ def test_fire_event(self): for offset, (event, function, *args) in enumerate(self.cases): with self.subTest(event): output = (function.__name__, offset, *args) - self.results = [] # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL sys.monitoring.register_callback(TEST_TOOL, event, self.cb) sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) active = 1 << TEST_TOOL try: + self.results = [] # fire one of each event type for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, active) self.assertEqual(self.results, [('cb',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) - @unittest.skip("disable not implemented yet") def test_disable_event(self): + events = sys.monitoring.events + cannot_disable = { events.PY_THROW, events.RAISE, events.RERAISE, + events.EXCEPTION_HANDLED, events.PY_UNWIND } + + def cb_disable(*args): + self.cb(*args) + return sys.monitoring.DISABLE + for offset, (event, function, *args) in enumerate(self.cases): - with self.subTest(event): + with self.subTest(function.__name__): output = (function.__name__, offset, *args) - self.results = [] - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - def cb(*args): - self.cb(*args) - return sys.monitoring.DISABLE - sys.monitoring.register_callback(TEST_TOOL, event, cb) + sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) active = 1 << TEST_TOOL try: # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) - self.assertEqual(self.results, [('cb',) + output]) - - # fire again - callbacks should be disabled now self.results = [] - for offset, (_, function, *args) in enumerate(self.cases): - function(function.__name__, offset, active, *args) - self.assertEqual(self.results, []) + for offset, (f_event, function, *args) in enumerate(self.cases): + if f_event == event and f_event in cannot_disable: + with self.assertRaises(ValueError): + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, active) + else: + res = function(function.__name__, offset, active, *args) + self.assertEqual(res, 0 if f_event == event else active) + self.assertEqual(self.results, [('cb',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 5b3ce297d7ad05..6b0e743a2b1860 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -15,7 +15,8 @@ fire_event_py_start(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyStartEvent(&state, codelike, offset)); + int res = _PyMonitoring_FirePyStartEvent(&state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -29,7 +30,8 @@ fire_event_py_resume(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyResumeEvent(&state, codelike, offset)); + int res = _PyMonitoring_FirePyResumeEvent(&state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -44,7 +46,8 @@ fire_event_py_return(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval)); + int res = _PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -59,7 +62,8 @@ fire_event_py_yield(PyObject *self, PyObject *args) } NULLABLE(codelike); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval)); + int res = _PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -75,7 +79,8 @@ fire_event_call(PyObject *self, PyObject *args) NULLABLE(callable); NULLABLE(arg0); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0)); + int res = _PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -90,7 +95,8 @@ fire_event_line(PyObject *self, PyObject *args) } NULLABLE(lineno); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireLineEvent(&state, codelike, offset, lineno)); + int res = _PyMonitoring_FireLineEvent(&state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -104,7 +110,8 @@ fire_event_jump(PyObject *self, PyObject *args) return NULL; } PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset)); + int res = _PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -118,7 +125,8 @@ fire_event_branch(PyObject *self, PyObject *args) return NULL; } PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset)); + int res = _PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -133,7 +141,8 @@ fire_event_py_throw(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -148,7 +157,8 @@ fire_event_raise(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -163,7 +173,8 @@ fire_event_reraise(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -178,7 +189,8 @@ fire_event_exception_handled(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -193,7 +205,8 @@ fire_event_py_unwind(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyObject * @@ -208,7 +221,8 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) } NULLABLE(exception); PyMonitoringState state = {active, 0}; - RETURN_INT(_PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception)); + int res = _PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state.active); } static PyMethodDef TestMethods[] = { diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 7f0b7f0e248c4b..c3fe37ec17b373 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2286,7 +2286,6 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t PyInterpreterState *interp = tstate->interp; uint8_t tools = state->active; -if (args[1]) _PyObject_Dump(args[1]); assert(args[1] == NULL); args[1] = codelike; PyObject *offset_obj = PyLong_FromLong(offset); @@ -2317,7 +2316,7 @@ if (args[1]) _PyObject_Dump(args[1]); /* DISABLE */ if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { PyErr_Format(PyExc_ValueError, - "Cannot disable %s events. Callback removed.", + "Cannot disable %s events. Callback removed.", event_names[event]); /* Clear tool to prevent infinite loop */ Py_CLEAR(interp->monitoring_callables[tool][event]); @@ -2325,7 +2324,7 @@ if (args[1]) _PyObject_Dump(args[1]); break; } else { - state->opaque &= ~(1 << tool); + state->active &= ~(1 << tool); } } } From 34179c1d83b146be9d06872adab76d446082b187 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 15:44:05 +0000 Subject: [PATCH 05/79] update PCbuild --- PCbuild/_testinternalcapi.vcxproj | 1 + PCbuild/_testinternalcapi.vcxproj.filters | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index a825cac9138674..f9b8c3f3fd97d1 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -98,6 +98,7 @@ + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index abfeeb39630daf..4347789b4715c5 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -21,10 +21,13 @@ Source Files + + Source Files + Resource Files - \ No newline at end of file + From 3c9f8bb706041c41fc492124aaf58011f3d89b50 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 7 Mar 2024 17:32:37 +0000 Subject: [PATCH 06/79] use int --- Modules/_testinternalcapi/monitoring.c | 42 +++++++++----------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 6b0e743a2b1860..08efae39c5b303 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -8,8 +8,7 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { return NULL; } @@ -23,8 +22,7 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { return NULL; } @@ -38,8 +36,7 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *retval; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { return NULL; @@ -54,8 +51,7 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *retval; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { return NULL; @@ -70,8 +66,7 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *callable, *arg0; if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { return NULL; @@ -87,8 +82,7 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *lineno; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { return NULL; @@ -103,8 +97,7 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; @@ -118,8 +111,7 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; @@ -133,8 +125,7 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -149,8 +140,7 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -165,8 +155,7 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -181,8 +170,7 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -197,8 +185,7 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; @@ -213,8 +200,7 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - uint32_t offset; - uint8_t active; + int offset, active; PyObject *exception; if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { return NULL; From 344fd265f753f886bb604218b5edf1c94b87da94 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 11 Mar 2024 09:02:13 +0000 Subject: [PATCH 07/79] implement _PyMonitoringScopeBegin and add CodeLike type --- Modules/_testinternalcapi/monitoring.c | 128 +++++++++++++++++++++++++ Python/instrumentation.c | 11 +++ 2 files changed, 139 insertions(+) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 08efae39c5b303..ff411027acb4e9 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -211,6 +211,126 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state.active); } +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat("(active=%dl, opaque=%dl)", + self->monitoring_states[i].active, + self->monitoring_states[i].opaque); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(" "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; + } + else { + return PyUnicode_FromString("PyCodeLikeObject"); + } +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + +static PyObject * +enter_scope_py_start_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike_obj; + if (!PyArg_ParseTuple(args, "O", &codelike_obj)) { + return NULL; + } + PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; + + uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; + _PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + + Py_RETURN_NONE; +} + static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, @@ -226,12 +346,20 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {"enter_scope_py_start_py_return", enter_scope_py_start_py_return, METH_VARARGS}, {NULL}, }; int _PyTestInternalCapi_Init_Monitoring(PyObject *m) { + if (PyType_Ready(&PyCodeLike_Type) < 0) { + return NULL; + } + if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { + Py_DECREF(m); + return NULL; + } if (PyModule_AddFunctions(m, TestMethods) < 0) { return -1; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index f0e519c1986e15..955747d8ca376d 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2343,6 +2343,17 @@ void _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (global_version(interp) == *version) { + return; + } + + _Py_GlobalMonitors *m = &interp->monitors; + for (uint32_t i = 0; i < length; i++) { + state_array[i].active = m->tools[event_types[i]]; + state_array[i].opaque = m->tools[event_types[i]]; + } + *version = global_version(interp); } int From ecaee5e8e4f6f7b5912c6d4cfa6ea02ecdb003a0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 11 Mar 2024 22:43:04 +0000 Subject: [PATCH 08/79] more tests --- Lib/test/test_monitoring.py | 84 ++++-- Modules/_testinternalcapi/monitoring.c | 351 ++++++++++++++----------- 2 files changed, 266 insertions(+), 169 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 3c3df1f8038c01..8b7687f291a929 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1877,14 +1877,14 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - def cb(*args): - self.results.append(('cb',) + args) + self.codelike = _testinternalcapi.CodeLike(2) - def cb2(*args): - self.results.append(('cb2',) + args) + def cb(name, args): + self.results.append((name,) + args) - self.cb = cb - self.cb2 = cb2 + self.cb1 = lambda codelike, *args : cb('cb1', args) + self.cb2 = lambda codelike, *args : cb('cb2', args) + self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events capi = _testinternalcapi @@ -1907,22 +1907,28 @@ def cb2(*args): ] def test_fire_event(self): - for offset, (event, function, *args) in enumerate(self.cases): + for event, function, *args in self.cases: + offset = 0 + self.codelike = _testinternalcapi.CodeLike(2) with self.subTest(event): - output = (function.__name__, offset, *args) + output = (offset, *args) # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb) + sys.monitoring.register_callback(TEST_TOOL, event, self.cb1) sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) active = 1 << TEST_TOOL try: self.results = [] # fire one of each event type - for offset, (_, function, *args) in enumerate(self.cases): - res = function(function.__name__, offset, active, *args) - self.assertEqual(res, active) - - self.assertEqual(self.results, [('cb',) + output]) + for _, function, *args in self.cases: + res = function(self.codelike, offset, active, *args) + try: + self.assertEqual(res, active) + except: + breakpoint() + raise + + self.assertEqual(self.results, [('cb1',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) @@ -1933,12 +1939,14 @@ def test_disable_event(self): events.EXCEPTION_HANDLED, events.PY_UNWIND } def cb_disable(*args): - self.cb(*args) + self.cb1(*args) return sys.monitoring.DISABLE - for offset, (event, function, *args) in enumerate(self.cases): + for event, function, *args in self.cases: + offset = 1 + self.codelike = _testinternalcapi.CodeLike(2) with self.subTest(function.__name__): - output = (function.__name__, offset, *args) + output = (offset, *args) sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) active = 1 << TEST_TOOL @@ -1946,16 +1954,48 @@ def cb_disable(*args): try: # fire one of each event type self.results = [] - for offset, (f_event, function, *args) in enumerate(self.cases): + for f_event, function, *args in self.cases: if f_event == event and f_event in cannot_disable: with self.assertRaises(ValueError): - res = function(function.__name__, offset, active, *args) - self.assertEqual(res, active) + res = function(self.codelike, offset, active, *args) + try: + self.assertEqual(res, active) + except: + breakpoint() + raise else: - res = function(function.__name__, offset, active, *args) + res = function(self.codelike, offset, active, *args) self.assertEqual(res, 0 if f_event == event else active) - self.assertEqual(self.results, [('cb',) + output]) + self.assertEqual(self.results, [('cb1',) + output]) finally: sys.monitoring.register_callback(TEST_TOOL, event, None) sys.monitoring.register_callback(TEST_TOOL2, event, None) + + def test_enter_scope(self): + events = sys.monitoring.events + capi = _testinternalcapi + + cl = _testinternalcapi.CodeLike(2) + capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb1', 0)]) + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_RETURN, self.cb2) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb1', 0), ('cb2', 1, 42)]) + + sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, None) + + self.results = [] + capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) + capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) + self.assertEqual(self.results, [('cb2', 1, 42)]) diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index ff411027acb4e9..7094acad3be7f1 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -3,6 +3,109 @@ #include "pycore_instruments.h" +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + if (self->monitoring_states) { + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat("(active=%d, opaque=%d)", + self->monitoring_states[i].active, + self->monitoring_states[i].opaque); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(": "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); + } +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + + +/*******************************************************************/ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) @@ -13,9 +116,13 @@ fire_event_py_start(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyStartEvent(&state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyStartEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -27,9 +134,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyResumeEvent(&state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyResumeEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -42,9 +153,13 @@ fire_event_py_return(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyReturnEvent(&state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -57,9 +172,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) return NULL; } NULLABLE(codelike); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyYieldEvent(&state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -71,11 +190,15 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { return NULL; } - NULLABLE(callable); + NULLABLE(codelike); NULLABLE(arg0); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireCallEvent(&state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -88,9 +211,13 @@ fire_event_line(PyObject *self, PyObject *args) return NULL; } NULLABLE(lineno); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireLineEvent(&state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -102,9 +229,13 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; } - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireJumpEvent(&state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -116,9 +247,13 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { return NULL; } - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireBranchEvent(&state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -131,9 +266,13 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyThrowEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -146,9 +285,13 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireRaiseEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -161,9 +304,13 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireReraiseEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -176,9 +323,13 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireExceptionHandledEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -191,9 +342,13 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FirePyUnwindEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; + + int res = _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } static PyObject * @@ -206,115 +361,17 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - PyMonitoringState state = {active, 0}; - int res = _PyMonitoring_FireStopIterationEvent(&state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state.active); -} - -typedef struct { - PyObject_HEAD - PyMonitoringState *monitoring_states; - uint64_t version; - int num_events; - /* Other fields */ -} PyCodeLikeObject; - - -static PyObject * -CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - int num_events; - if (!PyArg_ParseTuple(args, "i", &num_events)) { - return NULL; - } - PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( - num_events, sizeof(PyMonitoringState)); - if (states == NULL) { - return NULL; - } - PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); - if (self != NULL) { - self->version = 0; - self->monitoring_states = states; - self->num_events = num_events; - } - else { - PyMem_Free(states); - } - return (PyObject *) self; -} - -static void -CodeLike_dealloc(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyMem_Free(self->monitoring_states); - } - Py_TYPE(self)->tp_free((PyObject *) self); -} - -static PyObject * -CodeLike_str(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyObject *res = NULL; - PyObject *sep = NULL; - PyObject *parts = NULL; - - parts = PyList_New(0); - if (parts == NULL) { - goto end; - } - PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); - if (heading == NULL) { - goto end; - } - int err = PyList_Append(parts, heading); - Py_DECREF(heading); - if (err < 0) { - goto end; - } + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + state->active = active; - for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat("(active=%dl, opaque=%dl)", - self->monitoring_states[i].active, - self->monitoring_states[i].opaque); - if (part == NULL) { - goto end; - } - int err = PyList_Append(parts, part); - Py_XDECREF(part); - if (err < 0) { - goto end; - } - } - sep = PyUnicode_FromString(" "); - if (sep == NULL) { - goto end; - } - res = PyUnicode_Join(sep, parts); -end: - Py_XDECREF(sep); - Py_XDECREF(parts); - return res; - } - else { - return PyUnicode_FromString("PyCodeLikeObject"); - } + int res = _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); } -static PyTypeObject PyCodeLike_Type = { - .ob_base = PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "monitoring.CodeLike", - .tp_doc = PyDoc_STR("CodeLike objects"), - .tp_basicsize = sizeof(PyCodeLikeObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = CodeLike_new, - .tp_dealloc = (destructor) CodeLike_dealloc, - .tp_str = (reprfunc) CodeLike_str, -}; +/*******************************************************************/ static PyObject * enter_scope_py_start_py_return(PyObject *self, PyObject *args) @@ -354,11 +411,11 @@ int _PyTestInternalCapi_Init_Monitoring(PyObject *m) { if (PyType_Ready(&PyCodeLike_Type) < 0) { - return NULL; + return -1; } if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { Py_DECREF(m); - return NULL; + return -1; } if (PyModule_AddFunctions(m, TestMethods) < 0) { return -1; From 5c68095e2c555877bfa843dd3d229e2a349dd53a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 12 Mar 2024 23:30:39 +0000 Subject: [PATCH 09/79] make functions public --- Include/cpython/monitoring.h | 82 ++++++++ Include/internal/pycore_instruments.h | 83 -------- Include/monitoring.h | 276 +++++++++++++++++++++++++ Makefile.pre.in | 2 + Modules/_testinternalcapi/monitoring.c | 34 +-- Python/instrumentation.c | 194 +++++++++++++---- 6 files changed, 530 insertions(+), 141 deletions(-) create mode 100644 Include/cpython/monitoring.h create mode 100644 Include/monitoring.h diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h new file mode 100644 index 00000000000000..aa718e1113a1a9 --- /dev/null +++ b/Include/cpython/monitoring.h @@ -0,0 +1,82 @@ +#ifndef Py_CPYTHON_MONITORING_H +# error "this header file must not be included directly" +#endif + +void +_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); + +int +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +int +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); + +int +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + +int +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); + + +int +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); + +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); + +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +int +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); + +int +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); + diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 7be351e273e35f..7f84d4a763bbcf 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -101,89 +101,6 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index); extern PyObject _PyInstrumentation_MISSING; extern PyObject _PyInstrumentation_DISABLE; -typedef struct _PyMonitoringState { - uint8_t active; - uint8_t opaque; -} PyMonitoringState; - - -/*** C API ***/ - -PyAPI_FUNC(void) -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *retval); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *retval); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject* callable, PyObject *arg0); - - -PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *lineno); - -PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - - -PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *callable, PyObject *arg0); - -PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - -PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, - PyObject *exception); - #ifdef __cplusplus } #endif diff --git a/Include/monitoring.h b/Include/monitoring.h new file mode 100644 index 00000000000000..d6a1a6c4e7033c --- /dev/null +++ b/Include/monitoring.h @@ -0,0 +1,276 @@ +#ifndef Py_MONITORING_H +#define Py_MONITORING_H +#ifdef __cplusplus +extern "C" { + +#endif + +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + + +#ifndef Py_LIMITED_API +# define Py_CPYTHON_MONITORING_H +# include "cpython/monitoring.h" +# undef Py_CPYTHON_MONITORING_H + +#define IF_ACTIVE(X) \ + if (state->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + +#endif + + +#ifndef Py_LIMITED_API +static inline void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ + _PyMonitoringScopeBegin(state_array, version, event_types, length); +} +#else +extern void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); +#endif + + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} +#else +extern int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} +#else +extern int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno) +{ + IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} +#else +extern int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); +} +#else +extern int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} +#else +extern int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); +} +#else +extern int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); +} +#else +extern int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifndef Py_LIMITED_API +static inline int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} +#else +extern int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MONITORING_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index b1aaa594c9f6ef..21057d9c17d36b 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -989,6 +989,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/methodobject.h \ $(srcdir)/Include/modsupport.h \ $(srcdir)/Include/moduleobject.h \ + $(srcdir)/Include/monitoring.h \ $(srcdir)/Include/object.h \ $(srcdir)/Include/objimpl.h \ $(srcdir)/Include/opcode.h \ @@ -1059,6 +1060,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/longobject.h \ $(srcdir)/Include/cpython/memoryobject.h \ $(srcdir)/Include/cpython/methodobject.h \ + $(srcdir)/Include/cpython/monitoring.h \ $(srcdir)/Include/cpython/object.h \ $(srcdir)/Include/cpython/objimpl.h \ $(srcdir)/Include/cpython/odictobject.h \ diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testinternalcapi/monitoring.c index 7094acad3be7f1..26ce0e1bc0f67a 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testinternalcapi/monitoring.c @@ -1,7 +1,9 @@ #include "parts.h" #include "../_testcapi/util.h" // NULLABLE, RETURN_INT -#include "pycore_instruments.h" +#include "monitoring.h" + +#include "internal/pycore_instruments.h" typedef struct { PyObject_HEAD @@ -121,7 +123,7 @@ fire_event_py_start(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyStartEvent(state, codelike, offset); + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -139,7 +141,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyResumeEvent(state, codelike, offset); + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -158,7 +160,7 @@ fire_event_py_return(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -177,7 +179,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -197,7 +199,7 @@ fire_event_call(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); } @@ -216,7 +218,7 @@ fire_event_line(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); } @@ -234,7 +236,7 @@ fire_event_jump(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -252,7 +254,7 @@ fire_event_branch(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -271,7 +273,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -290,7 +292,7 @@ fire_event_raise(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -309,7 +311,7 @@ fire_event_reraise(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -328,7 +330,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -347,7 +349,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -367,7 +369,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) PyMonitoringState *state = &cl->monitoring_states[offset]; state->active = active; - int res = _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -383,7 +385,7 @@ enter_scope_py_start_py_return(PyObject *self, PyObject *args) PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - _PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 955747d8ca376d..1520931e386d45 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1,5 +1,6 @@ #include "Python.h" +#include "monitoring.h" #include "opcode_ids.h" #include "pycore_bitutils.h" // _Py_popcount32 @@ -2359,9 +2360,7 @@ _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; return capi_call_instrumentation(state, codelike, offset, args, 2, PY_MONITORING_EVENT_PY_START); @@ -2370,21 +2369,19 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uin int _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; return capi_call_instrumentation(state, codelike, offset, args, 2, PY_MONITORING_EVENT_PY_RESUME); } + + int _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* retval) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_RETURN); @@ -2394,9 +2391,7 @@ int _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* retval) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, retval }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_YIELD); @@ -2406,9 +2401,7 @@ int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[5] = { NULL, NULL, NULL, callable, arg0 }; return capi_call_instrumentation(state, codelike, offset, args, 4, PY_MONITORING_EVENT_CALL); @@ -2418,9 +2411,7 @@ int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, lineno }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_LINE); @@ -2430,9 +2421,7 @@ int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_JUMP); @@ -2442,9 +2431,7 @@ int _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_BRANCH); @@ -2454,9 +2441,7 @@ int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_THROW); @@ -2466,9 +2451,7 @@ int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); @@ -2478,9 +2461,7 @@ int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); @@ -2490,9 +2471,7 @@ int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); @@ -2502,9 +2481,7 @@ int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); @@ -2514,10 +2491,143 @@ int _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - if (!state->active) { - return 0; - } + assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, exception }; return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } + + + +#ifdef Py_LIMITED_API +void +PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) +{ + _PyMonitoringScopeBegin(state_array, version, event_types, length); +} + +int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} + +int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} + +int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} + +int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *retval) +{ + IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} + +int +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject* callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *lineno); +{ + IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} + +int +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +{ + IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); +} + +int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *target_offset) +{ + IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); +} + +int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception); +{ + IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *callable, PyObject *arg0) +{ + IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); +} + +int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, + PyObject *exception) +{ + IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} + +#endif From 7661865eba5eadd2304890af3c208e7201f13374 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:43:22 +0000 Subject: [PATCH 10/79] move tests from testinternalcapi to testcapi --- Include/cpython/monitoring.h | 43 +++++++++---------- Include/monitoring.h | 1 - .../monitoring.c | 5 ++- Modules/_testcapi/parts.h | 1 + Modules/_testcapimodule.c | 3 ++ Modules/_testinternalcapi.c | 3 -- Modules/_testinternalcapi/parts.h | 1 - PCbuild/_testinternalcapi.vcxproj | 1 - Python/instrumentation.c | 4 +- 9 files changed, 31 insertions(+), 31 deletions(-) rename Modules/{_testinternalcapi => _testcapi}/monitoring.c (99%) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index aa718e1113a1a9..d3e4445e199faa 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,81 +2,80 @@ # error "this header file must not be included directly" #endif -void +PyAPI_FUNC(void) _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + uint8_t *event_types, uint32_t length); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0); - -int +PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno); -int +PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index d6a1a6c4e7033c..d891c5c004e472 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -26,7 +26,6 @@ typedef struct _PyMonitoringState { #endif - #ifndef Py_LIMITED_API static inline void PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, diff --git a/Modules/_testinternalcapi/monitoring.c b/Modules/_testcapi/monitoring.c similarity index 99% rename from Modules/_testinternalcapi/monitoring.c rename to Modules/_testcapi/monitoring.c index 26ce0e1bc0f67a..c1d302ac177258 100644 --- a/Modules/_testinternalcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -1,8 +1,9 @@ #include "parts.h" -#include "../_testcapi/util.h" // NULLABLE, RETURN_INT +#include "util.h" #include "monitoring.h" +#define Py_BUILD_CORE #include "internal/pycore_instruments.h" typedef struct { @@ -410,7 +411,7 @@ static PyMethodDef TestMethods[] = { }; int -_PyTestInternalCapi_Init_Monitoring(PyObject *m) +_PyTestCapi_Init_Monitoring(PyObject *m) { if (PyType_Ready(&PyCodeLike_Type) < 0) { return -1; diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index e8cfb2423500d4..fe6b6f6eb9905a 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -60,6 +60,7 @@ int _PyTestCapi_Init_GC(PyObject *module); int _PyTestCapi_Init_Sys(PyObject *module); int _PyTestCapi_Init_Hash(PyObject *module); int _PyTestCapi_Init_Time(PyObject *module); +int _PyTestCapi_Init_Monitoring(PyObject *module); int _PyTestCapi_Init_VectorcallLimited(PyObject *module); int _PyTestCapi_Init_HeaptypeRelative(PyObject *module); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index b03f871b089c8a..b179e19c037233 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4110,6 +4110,9 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Time(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Monitoring(m) < 0) { + return NULL; + } PyState_AddModule(m, &_testcapimodule); return m; diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 4a04cbf63959f4..db8817418950b9 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1769,9 +1769,6 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } - if (_PyTestInternalCapi_Init_Monitoring(module) < 0) { - return 1; - } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index f8a8ab695ee145..49a1395f499fc3 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -14,6 +14,5 @@ int _PyTestInternalCapi_Init_Lock(PyObject *module); int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); -int _PyTestInternalCapi_Init_Monitoring(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index f9b8c3f3fd97d1..a825cac9138674 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -98,7 +98,6 @@ - diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1520931e386d45..a6e3892671b2c9 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2342,7 +2342,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t void _PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2500,6 +2500,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API + void PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) @@ -2507,6 +2508,7 @@ PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, _PyMonitoringScopeBegin(state_array, version, event_types, length); } + int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { From 580a9f3a4c3a908b08ad1502c94c47893f60b6cb Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:52:53 +0000 Subject: [PATCH 11/79] add include --- Include/Python.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/Python.h b/Include/Python.h index 01fc45137a17bb..f1b23855e33fba 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -78,6 +78,7 @@ #include "setobject.h" #include "methodobject.h" #include "moduleobject.h" +#include "monitoring.h" #include "cpython/funcobject.h" #include "cpython/classobject.h" #include "fileobject.h" From 19a1f90ba055c1c97ddba71b43e90902d6010026 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 11:53:44 +0000 Subject: [PATCH 12/79] PyMonitoringScopeBegin --> PyMonitoring_BeginScope --- Include/cpython/monitoring.h | 4 ++-- Include/monitoring.h | 10 +++++----- Modules/_sqlite/connection-dd92fcfb.o.tmp | 0 Modules/_sqlite/cursor-8e377591.o.tmp | 0 Modules/_testcapi/monitoring.c | 2 +- Python/instrumentation.c | 9 ++++----- 6 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 Modules/_sqlite/connection-dd92fcfb.o.tmp create mode 100644 Modules/_sqlite/cursor-8e377591.o.tmp diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index d3e4445e199faa..85c9356177fa61 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,8 +3,8 @@ #endif PyAPI_FUNC(void) -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); +_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index d891c5c004e472..e39d45ac74fa87 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -28,15 +28,15 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) { - _PyMonitoringScopeBegin(state_array, version, event_types, length); + _PyMonitoring_BeginScope(state_array, version, event_types, length); } #else extern void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length); #endif diff --git a/Modules/_sqlite/connection-dd92fcfb.o.tmp b/Modules/_sqlite/connection-dd92fcfb.o.tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Modules/_sqlite/cursor-8e377591.o.tmp b/Modules/_sqlite/cursor-8e377591.o.tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index c1d302ac177258..72972b17746428 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -386,7 +386,7 @@ enter_scope_py_start_py_return(PyObject *self, PyObject *args) PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - PyMonitoringScopeBegin(codelike->monitoring_states, &codelike->version, events, 2); + PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 2); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index a6e3892671b2c9..5ead3a005250a5 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1,6 +1,5 @@ #include "Python.h" -#include "monitoring.h" #include "opcode_ids.h" #include "pycore_bitutils.h" // _Py_popcount32 @@ -2341,8 +2340,8 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t } void -_PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) +_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, + uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2502,10 +2501,10 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API void -PyMonitoringScopeBegin(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { - _PyMonitoringScopeBegin(state_array, version, event_types, length); + _PyMonitoring_BeginScope(state_array, version, event_types, length); } From 745a2b3c33f1e7a141bd79ccaaa3d925039a1112 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 13:10:42 +0000 Subject: [PATCH 13/79] IF_ACTIVE --> _PyMonitoring_IF_ACTIVE --- Include/monitoring.h | 80 +++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/Include/monitoring.h b/Include/monitoring.h index e39d45ac74fa87..9009d4c47a865c 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -16,8 +16,8 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H -#define IF_ACTIVE(X) \ - if (state->active) { \ +#define _PyMonitoring_IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ return (X); \ } \ else { \ @@ -44,7 +44,9 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, static inline int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } #else extern int @@ -56,7 +58,9 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint static inline int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } #else extern int @@ -68,7 +72,9 @@ static inline int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } #else extern int @@ -81,7 +87,9 @@ static inline int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } #else extern int @@ -94,7 +102,9 @@ static inline int PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -107,7 +117,9 @@ static inline int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -120,7 +132,9 @@ static inline int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *lineno) { - IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } #else extern int @@ -132,7 +146,9 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_ static inline int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { - IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } #else extern int @@ -144,7 +160,9 @@ static inline int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } #else extern int @@ -157,7 +175,9 @@ static inline int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } #else extern int @@ -170,7 +190,9 @@ static inline int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -183,7 +205,9 @@ static inline int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } #else extern int @@ -196,7 +220,9 @@ static inline int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } #else extern int @@ -209,7 +235,9 @@ static inline int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } #else extern int @@ -222,7 +250,9 @@ static inline int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } #else extern int @@ -235,7 +265,9 @@ static inline int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); } #else extern int @@ -248,7 +280,9 @@ static inline int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } #else extern int @@ -261,7 +295,9 @@ static inline int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + _PyMonitoring_IF_ACTIVE( + state, + _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } #else extern int @@ -269,6 +305,10 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike PyObject *exception); #endif +#ifndef Py_LIMITED_API +#undef _PyMonitoring_IF_ACTIVE +#endif + #ifdef __cplusplus } #endif From ba5e7e08ed86e377d27ae5cef46cd7f756be9604 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 13:32:55 +0000 Subject: [PATCH 14/79] upate tests --- Lib/test/test_monitoring.py | 14 +++++++------- PCbuild/_testcapi.vcxproj | 1 + PCbuild/_testcapi.vcxproj.filters | 3 +++ PCbuild/_testinternalcapi.vcxproj.filters | 3 --- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 8b7687f291a929..d777478396ec56 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,7 +9,7 @@ import types import unittest import asyncio -import _testinternalcapi +import _testcapi from test import support from test.support import requires_specialization, script_helper @@ -1877,7 +1877,7 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) def cb(name, args): self.results.append((name,) + args) @@ -1887,7 +1887,7 @@ def cb(name, args): self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events - capi = _testinternalcapi + capi = _testcapi self.cases = [ # (Event, function, *args) (events.PY_START, capi.fire_event_py_start), @@ -1909,7 +1909,7 @@ def cb(name, args): def test_fire_event(self): for event, function, *args in self.cases: offset = 0 - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) with self.subTest(event): output = (offset, *args) # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL @@ -1944,7 +1944,7 @@ def cb_disable(*args): for event, function, *args in self.cases: offset = 1 - self.codelike = _testinternalcapi.CodeLike(2) + self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): output = (offset, *args) @@ -1974,9 +1974,9 @@ def cb_disable(*args): def test_enter_scope(self): events = sys.monitoring.events - capi = _testinternalcapi + capi = _testcapi - cl = _testinternalcapi.CodeLike(2) + cl = _testcapi.CodeLike(2) capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 66df0a61b5b5a6..3e1843a5da236c 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -128,6 +128,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index 651eb1d6ba0b7f..ab3660a386a6f3 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -111,6 +111,9 @@ Source Files + + Source Files + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 4347789b4715c5..27429ea5833077 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -21,9 +21,6 @@ Source Files - - Source Files - From aa19675bb85208b0e457a2c5d3875fef96221177 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 16:51:53 +0000 Subject: [PATCH 15/79] offset is int, event_types is const, remove "opaque" --- Include/cpython/monitoring.h | 40 +++++++++--------- Include/monitoring.h | 77 +++++++++++++++++----------------- Modules/_testcapi/monitoring.c | 4 +- Python/instrumentation.c | 37 ++++++++-------- 4 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 85c9356177fa61..ee8604e470cfbb 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -4,78 +4,78 @@ PyAPI_FUNC(void) _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + const uint8_t *event_types, uint32_t length); PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index 9009d4c47a865c..b9ea22e7157613 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -7,7 +7,6 @@ extern "C" { typedef struct _PyMonitoringState { uint8_t active; - uint8_t opaque; } PyMonitoringState; @@ -29,20 +28,20 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { _PyMonitoring_BeginScope(state_array, version, event_types, length); } #else extern void PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length); + const uint8_t *event_types, uint32_t length); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -50,13 +49,13 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -64,12 +63,12 @@ PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { _PyMonitoring_IF_ACTIVE( @@ -78,13 +77,13 @@ PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { _PyMonitoring_IF_ACTIVE( @@ -93,13 +92,13 @@ PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -108,13 +107,13 @@ PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -123,13 +122,13 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno) { _PyMonitoring_IF_ACTIVE( @@ -138,13 +137,13 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, @@ -152,12 +151,12 @@ PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, } #else extern int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( @@ -166,13 +165,13 @@ PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_ } #else extern int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( @@ -181,13 +180,13 @@ PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -196,13 +195,13 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -211,13 +210,13 @@ PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -226,13 +225,13 @@ PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32 } #else extern int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -241,13 +240,13 @@ PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint } #else extern int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -256,13 +255,13 @@ PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codel } #else extern int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( @@ -271,13 +270,13 @@ PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 } #else extern int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -286,13 +285,13 @@ PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uin } #else extern int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { _PyMonitoring_IF_ACTIVE( @@ -301,7 +300,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike } #else extern int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); #endif diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 72972b17746428..2dea857c5a7762 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -71,9 +71,7 @@ CodeLike_str(PyCodeLikeObject *self) } for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat("(active=%d, opaque=%d)", - self->monitoring_states[i].active, - self->monitoring_states[i].opaque); + PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); if (part == NULL) { goto end; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5ead3a005250a5..6f0be1f9d218f2 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2287,7 +2287,7 @@ PyObject *_Py_CreateMonitoringObject(void) static int -capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offset, PyObject **args, Py_ssize_t nargs, int event) { PyThreadState *tstate = _PyThreadState_GET(); @@ -2296,6 +2296,10 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t uint8_t tools = state->active; assert(args[1] == NULL); args[1] = codelike; + if (offset < 0) { + PyErr_SetString(PyExc_ValueError, "offset must be non-negative"); + return -1; + } PyObject *offset_obj = PyLong_FromLong(offset); if (offset_obj == NULL) { return -1; @@ -2341,7 +2345,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, uint32_t void _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2351,13 +2355,12 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _Py_GlobalMonitors *m = &interp->monitors; for (uint32_t i = 0; i < length; i++) { state_array[i].active = m->tools[event_types[i]]; - state_array[i].opaque = m->tools[event_types[i]]; } *version = global_version(interp); } int -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2366,7 +2369,7 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2377,7 +2380,7 @@ _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, ui int -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* retval) { assert(state->active); @@ -2387,7 +2390,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, ui } int -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* retval) { assert(state->active); @@ -2397,7 +2400,7 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { assert(state->active); @@ -2407,7 +2410,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno) { assert(state->active); @@ -2417,7 +2420,7 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { assert(state->active); @@ -2427,7 +2430,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32 } int -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { assert(state->active); @@ -2437,7 +2440,7 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint } int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2447,7 +2450,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2457,7 +2460,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint3 } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2467,7 +2470,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uin } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2477,7 +2480,7 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); @@ -2487,7 +2490,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, ui } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { assert(state->active); From 68aa35202812dedd382f0879ff45dbc4038076a5 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 17:36:01 +0000 Subject: [PATCH 16/79] PyMonitoring_FireLineEvent takes lineno as int --- Include/cpython/monitoring.h | 2 +- Include/monitoring.h | 4 ++-- Modules/_testcapi/monitoring.c | 6 ++---- Python/instrumentation.c | 14 ++++++++++---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index ee8604e470cfbb..8a42d778aafbff 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -30,7 +30,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno); PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index b9ea22e7157613..5d1f735ab83b04 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -129,7 +129,7 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int off #ifndef Py_LIMITED_API static inline int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno) + int lineno) { _PyMonitoring_IF_ACTIVE( state, @@ -138,7 +138,7 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off #else extern int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno); #endif #ifndef Py_LIMITED_API diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 2dea857c5a7762..1e1527e5838870 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -206,12 +206,10 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - PyObject *lineno; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &lineno)) { + int offset, active, lineno; + if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &active, &lineno)) { return NULL; } - NULLABLE(lineno); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 6f0be1f9d218f2..375fd3f334549f 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2411,12 +2411,18 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno) + int lineno) { assert(state->active); - PyObject *args[4] = { NULL, NULL, NULL, lineno }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_LINE); + PyObject *lno = PyLong_FromLong(lineno); + if (lno == NULL) { + return -1; + } + PyObject *args[4] = { NULL, NULL, NULL, lno }; + int res= capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_LINE); + Py_DECREF(lno); + return res; } int From db4e3b80e7ccd5065d879bb17b7416c468182736 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 17:48:34 +0000 Subject: [PATCH 17/79] add news --- .../next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst diff --git a/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst b/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst new file mode 100644 index 00000000000000..e74c0397b85aa1 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-03-13-17-48-24.gh-issue-111997.8ZbHlA.rst @@ -0,0 +1 @@ +Add a C-API for firing monitoring events. From 445b19fb3154368ec1e4daeedfe8b79a05bf9e1c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 18:17:37 +0000 Subject: [PATCH 18/79] remove debug stuff --- Lib/test/test_monitoring.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 82138172b82783..abb759b0431271 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1937,11 +1937,7 @@ def test_fire_event(self): # fire one of each event type for _, function, *args in self.cases: res = function(self.codelike, offset, active, *args) - try: - self.assertEqual(res, active) - except: - breakpoint() - raise + self.assertEqual(res, active) self.assertEqual(self.results, [('cb1',) + output]) finally: @@ -1973,11 +1969,7 @@ def cb_disable(*args): if f_event == event and f_event in cannot_disable: with self.assertRaises(ValueError): res = function(self.codelike, offset, active, *args) - try: - self.assertEqual(res, active) - except: - breakpoint() - raise + self.assertEqual(res, active) else: res = function(self.codelike, offset, active, *args) self.assertEqual(res, 0 if f_event == event else active) From 33ce7aaa1b43c878832099f59a03060939acbe18 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 23:11:31 +0000 Subject: [PATCH 19/79] not static --- Modules/_testcapi/monitoring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 1e1527e5838870..ec4a640a7f8161 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -93,7 +93,7 @@ CodeLike_str(PyCodeLikeObject *self) return res; } -static PyTypeObject PyCodeLike_Type = { +PyTypeObject PyCodeLike_Type = { .ob_base = PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "monitoring.CodeLike", .tp_doc = PyDoc_STR("CodeLike objects"), From cf6e20dad3d9dd0396f40a22d9054e0af348bc83 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 13 Mar 2024 23:51:30 +0000 Subject: [PATCH 20/79] Revert "not static" This reverts commit 33ce7aaa1b43c878832099f59a03060939acbe18. --- Modules/_testcapi/monitoring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index ec4a640a7f8161..1e1527e5838870 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -93,7 +93,7 @@ CodeLike_str(PyCodeLikeObject *self) return res; } -PyTypeObject PyCodeLike_Type = { +static PyTypeObject PyCodeLike_Type = { .ob_base = PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "monitoring.CodeLike", .tp_doc = PyDoc_STR("CodeLike objects"), From 89b05f14f496624262d7429c1759c8986b6cc07a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 11:37:19 +0000 Subject: [PATCH 21/79] ignore PyCodeLike_Type --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 686a3d3160cc90..dc338ab0e29722 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,6 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - +Modules/_testcapi/monitoring.c - PyCodeLike_Type ##----------------------- ## non-static types - initialized once From 5f727256d92574e35e7aac95c51c8506b453241b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 13:22:14 +0000 Subject: [PATCH 22/79] typo --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index dc338ab0e29722..c01bfb3239448b 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,7 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - -Modules/_testcapi/monitoring.c - PyCodeLike_Type +Modules/_testcapi/monitoring.c - PyCodeLike_Type - ##----------------------- ## non-static types - initialized once From 6368b42c9e83c818a3a0d33444676a9853b1ef03 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 14 Mar 2024 16:50:19 +0000 Subject: [PATCH 23/79] space to tab --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c01bfb3239448b..ae279c0c0237d3 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -395,7 +395,7 @@ Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - Modules/xxsubtype.c - spamdict_type - Modules/xxsubtype.c - spamlist_type - -Modules/_testcapi/monitoring.c - PyCodeLike_Type - +Modules/_testcapi/monitoring.c - PyCodeLike_Type - ##----------------------- ## non-static types - initialized once From e6d7c6a4bc5c74ff6d05036355dfcb6d0c79434e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 18 Mar 2024 17:09:55 +0000 Subject: [PATCH 24/79] skip test if no _testcapi --- Lib/test/test_monitoring.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index abb759b0431271..5e47a9dd1d3ccf 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -9,11 +9,12 @@ import types import unittest import asyncio -import _testcapi -from test import support +import test.support from test.support import requires_specialization, script_helper +_testcapi = test.support.import_helper.import_module("_testcapi") + PAIR = (0,1) def f1(): @@ -1883,7 +1884,7 @@ def test_monitoring_live_at_shutdown(self): # gh-115832: An object destructor running during the final GC of # interpreter shutdown triggered an infinite loop in the # instrumentation code. - script = support.findfile("_test_monitoring_shutdown.py") + script = test.support.findfile("_test_monitoring_shutdown.py") script_helper.run_test_script(script) @@ -1892,7 +1893,9 @@ class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): def setUp(self): super(TestCApiEventGeneration, self).setUp() - self.codelike = _testcapi.CodeLike(2) + capi = _testcapi + + self.codelike = capi.CodeLike(2) def cb(name, args): self.results.append((name,) + args) @@ -1902,7 +1905,6 @@ def cb(name, args): self.cb3 = lambda codelike, *args : cb('cb3', args) events = sys.monitoring.events - capi = _testcapi self.cases = [ # (Event, function, *args) (events.PY_START, capi.fire_event_py_start), @@ -1983,7 +1985,7 @@ def test_enter_scope(self): events = sys.monitoring.events capi = _testcapi - cl = _testcapi.CodeLike(2) + cl = capi.CodeLike(2) capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) From 58f2bcff1f20318f2444b230068671404d1dcd5c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 00:34:20 +0000 Subject: [PATCH 25/79] Code review comments --- Lib/test/test_monitoring.py | 172 ++++++++++++++++----------------- Modules/_testcapi/monitoring.c | 85 +++++++--------- Python/instrumentation.c | 3 +- 3 files changed, 120 insertions(+), 140 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 5e47a9dd1d3ccf..97c9417976b6ec 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -3,6 +3,7 @@ import collections import dis import functools +import math import operator import sys import textwrap @@ -1904,107 +1905,96 @@ def cb(name, args): self.cb2 = lambda codelike, *args : cb('cb2', args) self.cb3 = lambda codelike, *args : cb('cb3', args) - events = sys.monitoring.events self.cases = [ # (Event, function, *args) - (events.PY_START, capi.fire_event_py_start), - (events.PY_RESUME, capi.fire_event_py_resume), - (events.PY_RETURN, capi.fire_event_py_return, 10), - (events.PY_YIELD, capi.fire_event_py_yield, 20), - (events.CALL, capi.fire_event_call, callable, 30), - (events.LINE, capi.fire_event_line, 40), - (events.JUMP, capi.fire_event_jump, 50), - (events.BRANCH, capi.fire_event_branch, 60), - (events.PY_THROW, capi.fire_event_py_throw, ValueError(1)), - (events.RAISE, capi.fire_event_raise, ValueError(2)), - (events.RERAISE, capi.fire_event_reraise, ValueError(3)), - (events.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), - (events.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), - (events.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + (1, E.PY_START, capi.fire_event_py_start), + (1, E.PY_RESUME, capi.fire_event_py_resume), + (1, E.PY_RETURN, capi.fire_event_py_return, 10), + (1, E.PY_YIELD, capi.fire_event_py_yield, 20), + (2, E.CALL, capi.fire_event_call, callable, 30), + (3, E.LINE, capi.fire_event_line, 40), + (1, E.JUMP, capi.fire_event_jump, 50), + (1, E.BRANCH, capi.fire_event_branch, 60), + (1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + (1, E.RAISE, capi.fire_event_raise, ValueError(2)), + (1, E.RERAISE, capi.fire_event_reraise, ValueError(3)), + (1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), + (1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), + (1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), ] + def check_event_count(self, event, func, args, expected): + class Counter: + def __init__(self): + self.count = 0 + def __call__(self, *args): + self.count += 1 + + counter = Counter() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + prev = sys.monitoring.register_callback(TEST_TOOL, event, None) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, 0) + self.assertEqual(prev, counter) + sys.monitoring.set_events(TEST_TOOL, 0) + def test_fire_event(self): - for event, function, *args in self.cases: + for expected, event, function, *args in self.cases: offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(event): - output = (offset, *args) - # Register TEST_TOOL and TEST_TOOL2, but activate only TEST_TOOL - sys.monitoring.register_callback(TEST_TOOL, event, self.cb1) - sys.monitoring.register_callback(TEST_TOOL2, event, self.cb2) - active = 1 << TEST_TOOL + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args = (self.codelike, 0) + tuple(args) + self.check_event_count(event, function, args, expected) - try: - self.results = [] - # fire one of each event type - for _, function, *args in self.cases: - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, active) + CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, + E.EXCEPTION_HANDLED, E.PY_UNWIND } - self.assertEqual(self.results, [('cb1',) + output]) - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) + def check_disable(self, event, func, args, expected): + try: + counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + _testcapi.enter_scope_single_event(self.codelike, event_value) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.disable = True + if event in self.CANNOT_DISABLE: + with self.assertRaises(ValueError): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + else: + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected - 1) + sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.restart_events() def test_disable_event(self): - events = sys.monitoring.events - cannot_disable = { events.PY_THROW, events.RAISE, events.RERAISE, - events.EXCEPTION_HANDLED, events.PY_UNWIND } - - def cb_disable(*args): - self.cb1(*args) - return sys.monitoring.DISABLE - - for event, function, *args in self.cases: - offset = 1 + for expected, event, function, *args in self.cases: + offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - output = (offset, *args) - - sys.monitoring.register_callback(TEST_TOOL, event, cb_disable) - active = 1 << TEST_TOOL - - try: - # fire one of each event type - self.results = [] - for f_event, function, *args in self.cases: - if f_event == event and f_event in cannot_disable: - with self.assertRaises(ValueError): - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, active) - else: - res = function(self.codelike, offset, active, *args) - self.assertEqual(res, 0 if f_event == event else active) - self.assertEqual(self.results, [('cb1',) + output]) - - finally: - sys.monitoring.register_callback(TEST_TOOL, event, None) - sys.monitoring.register_callback(TEST_TOOL2, event, None) - - def test_enter_scope(self): - events = sys.monitoring.events - capi = _testcapi - - cl = capi.CodeLike(2) - capi.enter_scope_py_start_py_return(cl) # events = [PY_START, PY_RETURN] - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, self.cb1) - - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb1', 0)]) - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_RETURN, self.cb2) - - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb1', 0), ('cb2', 1, 42)]) - - sys.monitoring.register_callback(sys.monitoring.PROFILER_ID, events.PY_START, None) + args = (self.codelike, 0) + tuple(args) + self.check_disable(event, function, args, expected) - self.results = [] - capi.fire_event_py_start(cl, 0, 1 << sys.monitoring.PROFILER_ID) - capi.fire_event_py_return(cl, 1, 1 << sys.monitoring.PROFILER_ID, 42) - self.assertEqual(self.results, [('cb2', 1, 42)]) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 1e1527e5838870..dfb3d3b2d03c52 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -105,6 +105,7 @@ static PyTypeObject PyCodeLike_Type = { .tp_str = (reprfunc) CodeLike_str, }; +#define PyCodeLike_Check(v) Py_IS_TYPE((v), &PyCodeLike_Type) /*******************************************************************/ @@ -112,15 +113,14 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - NULLABLE(codelike); + assert(PyCodeLike_Check(codelike)); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -130,15 +130,14 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &active)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -148,16 +147,15 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); @@ -167,16 +165,15 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } NULLABLE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); @@ -186,9 +183,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &active, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } NULLABLE(codelike); @@ -196,7 +193,6 @@ fire_event_call(PyObject *self, PyObject *args) PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); @@ -206,14 +202,13 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active, lineno; - if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &active, &lineno)) { + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); @@ -223,15 +218,14 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -241,15 +235,14 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); @@ -259,16 +252,15 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -278,16 +270,15 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -297,16 +288,15 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -316,16 +306,15 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -335,16 +324,15 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -354,9 +342,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, active; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &active, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -364,7 +352,6 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - state->active = active; int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); @@ -373,16 +360,18 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) /*******************************************************************/ static PyObject * -enter_scope_py_start_py_return(PyObject *self, PyObject *args) +enter_scope_single_event(PyObject *self, PyObject *args) { PyObject *codelike_obj; - if (!PyArg_ParseTuple(args, "O", &codelike_obj)) { + int event; + if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event)) { return NULL; } PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; - uint8_t events[] = { PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RETURN }; - PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 2); + uint8_t events[] = { event }; + + PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 1); Py_RETURN_NONE; } @@ -402,7 +391,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope_py_start_py_return", enter_scope_py_start_py_return, METH_VARARGS}, + {"enter_scope_single_event", enter_scope_single_event, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 375fd3f334549f..60908b1b3fd620 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2354,7 +2354,8 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _Py_GlobalMonitors *m = &interp->monitors; for (uint32_t i = 0; i < length; i++) { - state_array[i].active = m->tools[event_types[i]]; + int event = event_types[i]; + state_array[i].active = m->tools[event]; } *version = global_version(interp); } From db5a28693bcfaf8dce378fedf59ec8383f722e3c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 12:36:40 +0000 Subject: [PATCH 26/79] remove unused --- Lib/test/test_monitoring.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 97c9417976b6ec..d35d415fc1b58b 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1898,13 +1898,6 @@ def setUp(self): self.codelike = capi.CodeLike(2) - def cb(name, args): - self.results.append((name,) + args) - - self.cb1 = lambda codelike, *args : cb('cb1', args) - self.cb2 = lambda codelike, *args : cb('cb2', args) - self.cb3 = lambda codelike, *args : cb('cb3', args) - self.cases = [ # (Event, function, *args) (1, E.PY_START, capi.fire_event_py_start), From 38346e8e6df67ec6932bff4723bd7c8a36b7f224 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 14:46:14 +0000 Subject: [PATCH 27/79] add test with two events --- Lib/test/test_monitoring.py | 42 +++++++++++++++++++++++++++++++--- Modules/_testcapi/monitoring.c | 26 +++++++++++++++------ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index e85582be0f13a7..ca427bc10b456d 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1933,12 +1933,12 @@ def __call__(self, *args): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, expected) prev = sys.monitoring.register_callback(TEST_TOOL, event, None) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, 0) @@ -1965,7 +1965,7 @@ def check_disable(self, event, func, args, expected): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope_single_event(self.codelike, event_value) + _testcapi.enter_scope(self.codelike, event_value) counter.count = 0 func(*args) self.assertEqual(counter.count, expected) @@ -1994,3 +1994,39 @@ def test_disable_event(self): args = (self.codelike, 0) + tuple(args) self.check_disable(event, function, args, expected) + def test_enter_scope_two_events(self): + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + _testcapi.enter_scope(cl, yield_value, unwind_value) + + assert(yield_counter.count == 0) + assert(unwind_counter.count == 0) + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.restart_events() diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index dfb3d3b2d03c52..fe7edb6e7345ca 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -360,18 +360,30 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) /*******************************************************************/ static PyObject * -enter_scope_single_event(PyObject *self, PyObject *args) +enter_scope(PyObject *self, PyObject *args) { PyObject *codelike_obj; - int event; - if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event)) { - return NULL; + int event1, event2=0; + int num_events = PyTuple_Size(args) - 1; + if (num_events == 1) { + if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event1)) { + return NULL; + } + } + else { + assert(num_events == 2); + if (!PyArg_ParseTuple(args, "Oii", &codelike_obj, &event1, &event2)) { + return NULL; + } } PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; - uint8_t events[] = { event }; + uint8_t events[] = { event1, event2 }; - PyMonitoring_BeginScope(codelike->monitoring_states, &codelike->version, events, 1); + PyMonitoring_BeginScope(codelike->monitoring_states, + &codelike->version, + events, + num_events); Py_RETURN_NONE; } @@ -391,7 +403,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope_single_event", enter_scope_single_event, METH_VARARGS}, + {"enter_scope", enter_scope, METH_VARARGS}, {NULL}, }; From f5c40fc634e51226e92d43fd880466fc72f3b3f7 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 21:22:54 +0000 Subject: [PATCH 28/79] add _PyMonitoring_EndScope --- Include/cpython/monitoring.h | 3 + Include/monitoring.h | 11 +++ Lib/test/test_monitoring.py | 118 ++++++++++++++++++--------------- Modules/_testcapi/monitoring.c | 7 ++ Python/instrumentation.c | 9 +++ 5 files changed, 95 insertions(+), 53 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 8a42d778aafbff..cacc338793a45c 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -6,6 +6,9 @@ PyAPI_FUNC(void) _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); +PyAPI_FUNC(void) +_PyMonitoring_EndScope(void); + PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 5d1f735ab83b04..4a895c18330a69 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -38,6 +38,17 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); #endif +#ifndef Py_LIMITED_API +static inline void +PyMonitoring_EndScope(void) +{ + _PyMonitoring_EndScope(); +} +#else +extern void +PyMonitoring_EndScope(void); +#endif + #ifndef Py_LIMITED_API static inline int diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index ca427bc10b456d..15a04671bff984 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1894,6 +1894,16 @@ def test_monitoring_live_at_shutdown(self): class TestCApiEventGeneration(MonitoringTestBase, unittest.TestCase): + class Scope: + def __init__(self, *args): + self.args = args + + def __enter__(self): + _testcapi.enter_scope(*self.args) + + def __exit__(self, *args): + _testcapi.exit_scope() + def setUp(self): super(TestCApiEventGeneration, self).setUp() @@ -1926,24 +1936,27 @@ def __init__(self): def __call__(self, *args): self.count += 1 - counter = Counter() - sys.monitoring.register_callback(TEST_TOOL, event, counter) - if event == E.C_RETURN or event == E.C_RAISE: - sys.monitoring.set_events(TEST_TOOL, E.CALL) - else: - sys.monitoring.set_events(TEST_TOOL, event) - event_value = int(math.log2(event)) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - prev = sys.monitoring.register_callback(TEST_TOOL, event, None) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, 0) - self.assertEqual(prev, counter) - sys.monitoring.set_events(TEST_TOOL, 0) + try: + counter = Counter() + sys.monitoring.register_callback(TEST_TOOL, event, counter) + if event == E.C_RETURN or event == E.C_RAISE: + sys.monitoring.set_events(TEST_TOOL, E.CALL) + else: + sys.monitoring.set_events(TEST_TOOL, event) + event_value = int(math.log2(event)) + with self.Scope(self.codelike, event_value): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + + prev = sys.monitoring.register_callback(TEST_TOOL, event, None) + with self.Scope(self.codelike, event_value): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, 0) + self.assertEqual(prev, counter) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) def test_fire_event(self): for expected, event, function, *args in self.cases: @@ -1965,23 +1978,23 @@ def check_disable(self, event, func, args, expected): else: sys.monitoring.set_events(TEST_TOOL, event) event_value = int(math.log2(event)) - _testcapi.enter_scope(self.codelike, event_value) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - counter.disable = True - if event in self.CANNOT_DISABLE: - with self.assertRaises(ValueError): - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) - else: + with self.Scope(self.codelike, event_value): counter.count = 0 func(*args) self.assertEqual(counter.count, expected) - counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected - 1) + counter.disable = True + if event in self.CANNOT_DISABLE: + with self.assertRaises(ValueError): + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + else: + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected) + counter.count = 0 + func(*args) + self.assertEqual(counter.count, expected - 1) sys.monitoring.set_events(TEST_TOOL, 0) finally: sys.monitoring.restart_events() @@ -2005,27 +2018,26 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) - _testcapi.enter_scope(cl, yield_value, unwind_value) - - assert(yield_counter.count == 0) - assert(unwind_counter.count == 0) - - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) sys.monitoring.set_events(TEST_TOOL, 0) finally: diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index fe7edb6e7345ca..bd913c0323bc45 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -388,6 +388,12 @@ enter_scope(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +exit_scope(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, @@ -404,6 +410,7 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, {"enter_scope", enter_scope, METH_VARARGS}, + {"exit_scope", exit_scope, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 60908b1b3fd620..c83218b6ed48c6 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2360,6 +2360,11 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, *version = global_version(interp); } +void +_PyMonitoring_EndScope(void) +{ +} + int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -2517,6 +2522,10 @@ PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, _PyMonitoring_BeginScope(state_array, version, event_types, length); } +void +PyMonitoring_EndScope() +{ +} int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) From 95c5275304a41c16e88f935b5f7e76e5c8c01eba Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 22:22:21 +0000 Subject: [PATCH 29/79] Begin/End --> Enter/Exit --- Include/cpython/monitoring.h | 4 ++-- Include/monitoring.h | 12 ++++++------ Modules/_testcapi/monitoring.c | 3 ++- Python/instrumentation.c | 10 +++++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index cacc338793a45c..c2ce3fd6a25fee 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,11 +3,11 @@ #endif PyAPI_FUNC(void) -_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) -_PyMonitoring_EndScope(void); +_PyMonitoring_ExitScope(void); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 4a895c18330a69..9ba4c2b3ac0a6f 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -27,26 +27,26 @@ typedef struct _PyMonitoringState { #ifndef Py_LIMITED_API static inline void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { - _PyMonitoring_BeginScope(state_array, version, event_types, length); + _PyMonitoring_EnterScope(state_array, version, event_types, length); } #else extern void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); #endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_EndScope(void) +PyMonitoring_ExitScope(void) { - _PyMonitoring_EndScope(); + _PyMonitoring_ExitScope(); } #else extern void -PyMonitoring_EndScope(void); +PyMonitoring_ExitScope(void); #endif diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index bd913c0323bc45..9737f5e2f60176 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -380,7 +380,7 @@ enter_scope(PyObject *self, PyObject *args) uint8_t events[] = { event1, event2 }; - PyMonitoring_BeginScope(codelike->monitoring_states, + PyMonitoring_EnterScope(codelike->monitoring_states, &codelike->version, events, num_events); @@ -391,6 +391,7 @@ enter_scope(PyObject *self, PyObject *args) static PyObject * exit_scope(PyObject *self, PyObject *args) { + PyMonitoring_ExitScope(); Py_RETURN_NONE; } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index c83218b6ed48c6..8f8352113e0505 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2344,7 +2344,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs } void -_PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -2361,7 +2361,7 @@ _PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, } void -_PyMonitoring_EndScope(void) +_PyMonitoring_ExitScope(void) { } @@ -2516,14 +2516,14 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik #ifdef Py_LIMITED_API void -PyMonitoring_BeginScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) { - _PyMonitoring_BeginScope(state_array, version, event_types, length); + _PyMonitoring_EnterScope(state_array, version, event_types, length); } void -PyMonitoring_EndScope() +PyMonitoring_ExitScope() { } From 427e1162c8e388e9b24c890415b00f13ad1cd4fa Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 22:58:28 +0000 Subject: [PATCH 30/79] error checking --- Modules/_testcapi/monitoring.c | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 9737f5e2f60176..a7146f4236e506 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -105,7 +105,10 @@ static PyTypeObject PyCodeLike_Type = { .tp_str = (reprfunc) CodeLike_str, }; -#define PyCodeLike_Check(v) Py_IS_TYPE((v), &PyCodeLike_Type) +#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ + PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ + return NULL; \ + } /*******************************************************************/ @@ -117,7 +120,7 @@ fire_event_py_start(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - assert(PyCodeLike_Check(codelike)); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -134,7 +137,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -152,7 +155,7 @@ fire_event_py_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -170,7 +173,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - NULLABLE(codelike); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -188,8 +191,8 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - NULLABLE(codelike); NULLABLE(arg0); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -206,6 +209,7 @@ fire_event_line(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -223,6 +227,7 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -240,6 +245,7 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -258,6 +264,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -276,6 +283,7 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -294,6 +302,7 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -312,6 +321,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -330,6 +340,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -348,7 +359,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } NULLABLE(exception); - + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -362,26 +373,27 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) static PyObject * enter_scope(PyObject *self, PyObject *args) { - PyObject *codelike_obj; + PyObject *codelike; int event1, event2=0; int num_events = PyTuple_Size(args) - 1; if (num_events == 1) { - if (!PyArg_ParseTuple(args, "Oi", &codelike_obj, &event1)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { return NULL; } } else { assert(num_events == 2); - if (!PyArg_ParseTuple(args, "Oii", &codelike_obj, &event1, &event2)) { + if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { return NULL; } } - PyCodeLikeObject *codelike = (PyCodeLikeObject *) codelike_obj; + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; uint8_t events[] = { event1, event2 }; - PyMonitoring_EnterScope(codelike->monitoring_states, - &codelike->version, + PyMonitoring_EnterScope(cl->monitoring_states, + &cl->version, events, num_events); From 3bc47df115f02d3d6242a2bf5426da638c2908a8 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:15:05 +0000 Subject: [PATCH 31/79] review comments --- Modules/_testcapi/monitoring.c | 2 +- Python/instrumentation.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index a7146f4236e506..7ece3987972cc6 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -375,7 +375,7 @@ enter_scope(PyObject *self, PyObject *args) { PyObject *codelike; int event1, event2=0; - int num_events = PyTuple_Size(args) - 1; + Py_ssize_t num_events = PyTuple_Size(args) - 1; if (num_events == 1) { if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { return NULL; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 8f8352113e0505..0d4efc5c5baefe 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2511,9 +2511,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik PY_MONITORING_EVENT_STOP_ITERATION); } - - -#ifdef Py_LIMITED_API +/******************* Public API *******************/ void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, @@ -2649,5 +2647,3 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } - -#endif From 5f11cdaabcb968449fab4c139a04d6bf24a0c188 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:20:45 +0000 Subject: [PATCH 32/79] uint32_t --> int --- Python/instrumentation.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 0d4efc5c5baefe..efcb6b5ec84b5a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2526,123 +2526,123 @@ PyMonitoring_ExitScope() } int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); } int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *lineno); { IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); } int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); } int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); { IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *callable, PyObject *arg0) { IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); } int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); From e719e38fcf4f825b6aa1b848956a61f6d2e2217b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Mar 2024 23:21:19 +0000 Subject: [PATCH 33/79] put ifdef back --- Python/instrumentation.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index efcb6b5ec84b5a..777ee1e6d711a2 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2513,6 +2513,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ +#ifdef Py_LIMITED_API void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, uint8_t *event_types, uint32_t length) @@ -2647,3 +2648,5 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike { IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } + +#endif From be236b170b3d717ec24c73862136e570315cf234 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 20 Mar 2024 15:57:58 +0000 Subject: [PATCH 34/79] add opaque --- Include/monitoring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/monitoring.h b/Include/monitoring.h index 9ba4c2b3ac0a6f..ce50b844775c4f 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -7,6 +7,7 @@ extern "C" { typedef struct _PyMonitoringState { uint8_t active; + uint8_t opaque; } PyMonitoringState; From 8c1eacf5bee27404f7b721dba1da0e758929fb3a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 20 Mar 2024 23:47:42 +0000 Subject: [PATCH 35/79] always define the private versions. PyUnstable_ for the inlined --- Include/cpython/monitoring.h | 85 ++++++++++++++++- Include/monitoring.h | 170 +++++++++++++++------------------ Lib/test/test_monitoring.py | 35 ++++--- Modules/_testcapi/monitoring.c | 57 +++++++++++ Python/instrumentation.c | 106 ++++++++++++-------- 5 files changed, 302 insertions(+), 151 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index c2ce3fd6a25fee..3c536a26efd8f8 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -3,82 +3,161 @@ #endif PyAPI_FUNC(void) +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length); + +void _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) +PyMonitoring_ExitScope(void); + +void _PyMonitoring_ExitScope(void); PyAPI_FUNC(int) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +int _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +int _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno); + +int _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); PyAPI_FUNC(int) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +int _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +int _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); PyAPI_FUNC(int) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +int _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); + PyObject *retval); PyAPI_FUNC(int) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); + PyObject *exception); PyAPI_FUNC(int) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); +int +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index ce50b844775c4f..f6348a268c2d15 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -2,7 +2,6 @@ #define Py_MONITORING_H #ifdef __cplusplus extern "C" { - #endif typedef struct _PyMonitoringState { @@ -11,7 +10,6 @@ typedef struct _PyMonitoringState { } PyMonitoringState; -#ifndef Py_LIMITED_API # define Py_CPYTHON_MONITORING_H # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H @@ -24,301 +22,283 @@ typedef struct _PyMonitoringState { return 0; \ } -#endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) +PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } -#else +#endif + extern void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -#endif #ifndef Py_LIMITED_API static inline void -PyMonitoring_ExitScope(void) +PyUnstable_Monitoring_ExitScope(void) { _PyMonitoring_ExitScope(); } -#else +#endif + extern void PyMonitoring_ExitScope(void); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) +PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } -#else -extern int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); #endif -#ifndef Py_LIMITED_API -static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - _PyMonitoring_IF_ACTIVE( - state, - _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} -#else extern int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) +PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -#else +#endif + extern int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } -#else +#endif + extern int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } -#else +#endif + extern int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } -#else +#endif + extern int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) +PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } -#else +#endif + extern int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); -#endif + PyObject *retval); #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) +PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0); -#endif + PyObject *exception); #ifndef Py_LIMITED_API static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif #ifndef Py_LIMITED_API static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PyMonitoring_IF_ACTIVE( state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#else +#endif + extern int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif -#ifndef Py_LIMITED_API #undef _PyMonitoring_IF_ACTIVE -#endif #ifdef __cplusplus } diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 15a04671bff984..efdeb717a23e27 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1913,20 +1913,19 @@ def setUp(self): self.cases = [ # (Event, function, *args) - (1, E.PY_START, capi.fire_event_py_start), - (1, E.PY_RESUME, capi.fire_event_py_resume), - (1, E.PY_RETURN, capi.fire_event_py_return, 10), - (1, E.PY_YIELD, capi.fire_event_py_yield, 20), - (2, E.CALL, capi.fire_event_call, callable, 30), - (3, E.LINE, capi.fire_event_line, 40), - (1, E.JUMP, capi.fire_event_jump, 50), - (1, E.BRANCH, capi.fire_event_branch, 60), - (1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), - (1, E.RAISE, capi.fire_event_raise, ValueError(2)), - (1, E.RERAISE, capi.fire_event_reraise, ValueError(3)), - (1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(4)), - (1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(5)), - (1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(6)), + ( 1, E.PY_START, capi.fire_event_py_start), + ( 1, E.PY_RESUME, capi.fire_event_py_resume), + ( 1, E.PY_YIELD, capi.fire_event_py_yield, 10), + ( 1, E.PY_RETURN, capi.fire_event_py_return, 20), + ( 2, E.CALL, capi.fire_event_call, callable, 40), + (10, E.INSTRUCTION, capi.fire_event_instruction), + ( 1, E.JUMP, capi.fire_event_jump, 60), + ( 1, E.BRANCH, capi.fire_event_branch, 70), + ( 1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), + ( 1, E.RAISE, capi.fire_event_raise, ValueError(2)), + ( 1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(5)), + ( 1, E.PY_UNWIND, capi.fire_event_py_unwind, ValueError(6)), + ( 1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(7)), ] def check_event_count(self, event, func, args, expected): @@ -1984,10 +1983,16 @@ def check_disable(self, event, func, args, expected): self.assertEqual(counter.count, expected) counter.disable = True if event in self.CANNOT_DISABLE: - with self.assertRaises(ValueError): + # use try-except rather then assertRaises to avoid + # events from framework code + try: counter.count = 0 func(*args) self.assertEqual(counter.count, expected) + except ValueError: + pass + else: + self.Error("Expected a ValueError") else: counter.count = 0 func(*args) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 7ece3987972cc6..e3c8ead8f68d2f 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -164,6 +164,24 @@ fire_event_py_return(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { @@ -218,6 +236,23 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -292,6 +327,25 @@ fire_event_raise(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { @@ -411,13 +465,16 @@ static PyMethodDef TestMethods[] = { {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 777ee1e6d711a2..40802a571af172 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2431,6 +2431,16 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of return res; } +int +_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + assert(state->active); + PyObject *args[3] = { NULL, NULL, NULL }; + int res= capi_call_instrumentation(state, codelike, offset, args, 2, + PY_MONITORING_EVENT_INSTRUCTION); + return res; +} + int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -2451,6 +2461,16 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_BRANCH); } +int +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, retval }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RETURN); +} + int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -2471,6 +2491,16 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o PY_MONITORING_EVENT_RAISE); } +int +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, exception }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RAISE); +} + int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -2513,140 +2543,140 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ -#ifdef Py_LIMITED_API void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - uint8_t *event_types, uint32_t length) + const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } void -PyMonitoring_ExitScope() +PyMonitoring_ExitScope(void) { } +#define IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FirePyStartEvent(state, codelike, offset)); + IF_ACTIVE(state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FirePyResumeEvent(state, codelike, offset)); + IF_ACTIVE(state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); + IF_ACTIVE(state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - IF_ACTIVE(_PyMonitoring_FirePyCallEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { - IF_ACTIVE(_PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *lineno); + int lineno) { - IF_ACTIVE(_PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); + IF_ACTIVE(state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } int PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - IF_ACTIVE(_PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - -int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + IF_ACTIVE(state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); + IF_ACTIVE(state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - IF_ACTIVE(_PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + IF_ACTIVE(state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) + PyObject *retval) { - IF_ACTIVE(_PyMonitoring_FireCReturnEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); + PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + IF_ACTIVE(state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *callable, PyObject *arg0) + PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireCRaiseEvent(state, codelike, offset, callable, arg0)); + IF_ACTIVE(state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - IF_ACTIVE(_PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + IF_ACTIVE(state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#endif +#undef IF_ACTIVE From 23f579ba1d5e73050b073dd6e781c2a61ce21d65 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 13:42:40 +0000 Subject: [PATCH 36/79] add tests for the Unstable version of the API --- Include/cpython/monitoring.h | 42 +++---- Lib/test/test_monitoring.py | 92 +++++++-------- Modules/_testcapi/monitoring.c | 204 ++++++++++++++++++++++++--------- 3 files changed, 221 insertions(+), 117 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 3c536a26efd8f8..87f3d35d3d9894 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -6,33 +6,33 @@ PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -void +PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) PyMonitoring_ExitScope(void); -void +PyAPI_FUNC(void) _PyMonitoring_ExitScope(void); PyAPI_FUNC(int) PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -40,7 +40,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -48,7 +48,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -56,7 +56,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -int +PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -64,21 +64,21 @@ PyAPI_FUNC(int) PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -int +PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); PyAPI_FUNC(int) PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); PyAPI_FUNC(int) PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -86,7 +86,7 @@ PyAPI_FUNC(int) PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -94,7 +94,7 @@ PyAPI_FUNC(int) PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -int +PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); @@ -102,7 +102,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -int +PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); @@ -110,7 +110,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -118,7 +118,7 @@ PyAPI_FUNC(int) PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -126,7 +126,7 @@ PyAPI_FUNC(int) PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -134,7 +134,7 @@ PyAPI_FUNC(int) PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -142,7 +142,7 @@ PyAPI_FUNC(int) PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -150,7 +150,7 @@ PyAPI_FUNC(int) PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); @@ -158,6 +158,6 @@ PyAPI_FUNC(int) PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -int +PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index efdeb717a23e27..d8a6286030c5de 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1959,11 +1959,12 @@ def __call__(self, *args): def test_fire_event(self): for expected, event, function, *args in self.cases: - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with self.subTest(function.__name__): - args = (self.codelike, 0) + tuple(args) - self.check_event_count(event, function, args, expected) + for unstable in (0, 1): + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__, unstable=unstable): + args_ = (self.codelike, 0, unstable) + tuple(args) + self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } @@ -2000,50 +2001,51 @@ def check_disable(self, event, func, args, expected): counter.count = 0 func(*args) self.assertEqual(counter.count, expected - 1) - sys.monitoring.set_events(TEST_TOOL, 0) finally: - sys.monitoring.restart_events() + sys.monitoring.set_events(TEST_TOOL, 0) def test_disable_event(self): for expected, event, function, *args in self.cases: - offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(function.__name__): - args = (self.codelike, 0) + tuple(args) - self.check_disable(event, function, args, expected) + for unstable in (0, 1): + offset = 0 + self.codelike = _testcapi.CodeLike(2) + with self.subTest(function.__name__, unstable=unstable): + args_ = (self.codelike, 0, unstable) + tuple(args) + self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): - try: - yield_counter = CounterWithDisable() - unwind_counter = CounterWithDisable() - sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) - sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) - sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) - - yield_value = int(math.log2(E.PY_YIELD)) - unwind_value = int(math.log2(E.PY_UNWIND)) - cl = _testcapi.CodeLike(2) - with self.Scope(cl, yield_value, unwind_value): - yield_counter.count = 0 - unwind_counter.count = 0 - - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + for unstable in (0,1): + with self.subTest(unstable=unstable): + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) - sys.monitoring.set_events(TEST_TOOL, 0) - finally: - sys.monitoring.restart_events() + finally: + sys.monitoring.set_events(TEST_TOOL, 0) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e3c8ead8f68d2f..877cdb7245f802 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -116,8 +116,8 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -125,7 +125,13 @@ fire_event_py_start(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyStartEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -133,8 +139,8 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -142,7 +148,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyResumeEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -150,9 +162,9 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -160,7 +172,13 @@ fire_event_py_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyReturnEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -168,9 +186,9 @@ static PyObject * fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -178,7 +196,13 @@ fire_event_c_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCReturnEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -186,9 +210,9 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -196,7 +220,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyYieldEvent(state, codelike, offset, retval); + } + else { + res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -204,9 +234,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &unstable, &callable, &arg0)) { return NULL; } NULLABLE(arg0); @@ -215,7 +245,13 @@ fire_event_call(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCallEvent(state, codelike, offset, callable, arg0); + } + else { + res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -223,8 +259,8 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + int offset, unstable, lineno; + if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &unstable, &lineno)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -232,7 +268,13 @@ fire_event_line(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireLineEvent(state, codelike, offset, lineno); + } + else { + res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -240,8 +282,8 @@ static PyObject * fire_event_instruction(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + int offset, unstable; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -249,7 +291,13 @@ fire_event_instruction(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireInstructionEvent(state, codelike, offset); + } + else { + res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -257,9 +305,9 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -267,7 +315,13 @@ fire_event_jump(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireJumpEvent(state, codelike, offset, target_offset); + } + else { + res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -275,9 +329,9 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -285,7 +339,13 @@ fire_event_branch(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireBranchEvent(state, codelike, offset, target_offset); + } + else { + res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -293,9 +353,9 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -304,7 +364,13 @@ fire_event_py_throw(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyThrowEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -312,9 +378,9 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -323,7 +389,13 @@ fire_event_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireRaiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -331,9 +403,9 @@ static PyObject * fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -342,7 +414,13 @@ fire_event_c_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireCRaiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -350,9 +428,9 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -361,7 +439,13 @@ fire_event_reraise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireReraiseEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -369,9 +453,9 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -380,7 +464,13 @@ fire_event_exception_handled(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -388,9 +478,9 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -399,7 +489,13 @@ fire_event_py_unwind(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FirePyUnwindEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } @@ -407,9 +503,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset; + int offset, unstable; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { return NULL; } NULLABLE(exception); @@ -418,7 +514,13 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + int res; + if (unstable) { + res = PyUnstable_Monitoring_FireStopIterationEvent(state, codelike, offset, exception); + } + else { + res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + } RETURN_INT(res == -1 ? -1 : state->active); } From eee637e97a611d935563d978616fd4c53e103a91 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 14:10:21 +0000 Subject: [PATCH 37/79] tidy up declarations --- Include/cpython/monitoring.h | 80 --------------- Include/monitoring.h | 187 ++++++++++++++--------------------- 2 files changed, 75 insertions(+), 192 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 87f3d35d3d9894..deb64561a8332f 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,162 +2,82 @@ # error "this header file must not be included directly" #endif -PyAPI_FUNC(void) -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); -PyAPI_FUNC(void) -PyMonitoring_ExitScope(void); - PyAPI_FUNC(void) _PyMonitoring_ExitScope(void); -PyAPI_FUNC(int) -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -PyAPI_FUNC(int) -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); -PyAPI_FUNC(int) -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -PyAPI_FUNC(int) -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - PyAPI_FUNC(int) _PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); -PyAPI_FUNC(int) -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); diff --git a/Include/monitoring.h b/Include/monitoring.h index f6348a268c2d15..d71e02d3817f48 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -14,6 +14,79 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H +PyAPI_FUNC(void) +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, + const uint8_t *event_types, uint32_t length); + +PyAPI_FUNC(void) +PyMonitoring_ExitScope(void); + +PyAPI_FUNC(int) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0); + +PyAPI_FUNC(int) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno); + +PyAPI_FUNC(int) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); + +PyAPI_FUNC(int) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval); + +PyAPI_FUNC(int) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); +PyAPI_FUNC(int) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +PyAPI_FUNC(int) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception); + +#ifndef Py_LIMITED_API + #define _PyMonitoring_IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ return (X); \ @@ -23,32 +96,19 @@ typedef struct _PyMonitoringState { } -#ifndef Py_LIMITED_API static inline void PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { _PyMonitoring_EnterScope(state_array, version, event_types, length); } -#endif -extern void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - -#ifndef Py_LIMITED_API static inline void PyUnstable_Monitoring_ExitScope(void) { _PyMonitoring_ExitScope(); } -#endif -extern void -PyMonitoring_ExitScope(void); - - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -56,13 +116,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } -#endif -extern int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -70,12 +124,7 @@ PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } -#endif -extern int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -84,13 +133,7 @@ PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } -#endif -extern int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -99,13 +142,7 @@ PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } -#endif -extern int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) @@ -114,13 +151,7 @@ PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } -#endif -extern int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno) @@ -129,13 +160,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -#endif -extern int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { @@ -143,12 +168,7 @@ PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *c state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } -#endif - -extern int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -157,13 +177,7 @@ PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } -#endif -extern int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) @@ -172,13 +186,7 @@ PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codeli state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } -#endif -extern int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) @@ -187,13 +195,7 @@ PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } -#endif - -extern int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -202,13 +204,7 @@ PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -217,13 +213,7 @@ PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelik state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -232,13 +222,7 @@ PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codel state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -247,13 +231,7 @@ PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObje state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } -#endif -extern int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -262,13 +240,7 @@ PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codeli state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } -#endif -extern int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -277,13 +249,7 @@ PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *code state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -#ifndef Py_LIMITED_API static inline int PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) @@ -292,13 +258,10 @@ PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#endif - -extern int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); #undef _PyMonitoring_IF_ACTIVE +#endif + #ifdef __cplusplus } From 29c01e37e1183af1de17af6c19cfa090baad732d Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 21 Mar 2024 16:31:11 +0000 Subject: [PATCH 38/79] private versions are not in limited API --- Include/cpython/monitoring.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index deb64561a8332f..362fdf5e99ef80 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,6 +2,8 @@ # error "this header file must not be included directly" #endif +#ifndef Py_LIMITED_API + PyAPI_FUNC(void) _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); @@ -81,3 +83,5 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); + +#endif From ef9a4a1f179c264521ac235e6af45d68cc808141 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 25 Mar 2024 16:18:04 +0000 Subject: [PATCH 39/79] rename macro --- Include/monitoring.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Include/monitoring.h b/Include/monitoring.h index d71e02d3817f48..3e56f594790cb7 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -87,7 +87,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike #ifndef Py_LIMITED_API -#define _PyMonitoring_IF_ACTIVE(STATE, X) \ +#define _PYMONITORING_IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ return (X); \ } \ @@ -112,7 +112,7 @@ PyUnstable_Monitoring_ExitScope(void) static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); } @@ -120,7 +120,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel static inline int PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); } @@ -129,7 +129,7 @@ static inline int PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); } @@ -138,7 +138,7 @@ static inline int PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); } @@ -147,7 +147,7 @@ static inline int PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); } @@ -156,7 +156,7 @@ static inline int PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } @@ -164,7 +164,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike static inline int PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); } @@ -173,7 +173,7 @@ static inline int PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); } @@ -182,7 +182,7 @@ static inline int PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); } @@ -191,7 +191,7 @@ static inline int PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); } @@ -200,7 +200,7 @@ static inline int PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); } @@ -209,7 +209,7 @@ static inline int PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); } @@ -218,7 +218,7 @@ static inline int PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); } @@ -227,7 +227,7 @@ static inline int PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); } @@ -236,7 +236,7 @@ static inline int PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); } @@ -245,7 +245,7 @@ static inline int PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); } @@ -254,12 +254,12 @@ static inline int PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception) { - _PyMonitoring_IF_ACTIVE( + _PYMONITORING_IF_ACTIVE( state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); } -#undef _PyMonitoring_IF_ACTIVE +#undef _PYMONITORING_IF_ACTIVE #endif From c0bcc2205e8038af91821bdbefcaf9c3090deabd Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 26 Mar 2024 19:39:35 +0000 Subject: [PATCH 40/79] update limited API --- Doc/data/stable_abi.dat | 19 ++++++++++++++ Lib/test/test_stable_abi_ctypes.py | 19 ++++++++++++++ Misc/stable_abi.toml | 40 ++++++++++++++++++++++++++++++ PC/python3dll.c | 19 ++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 2763bea5137cc7..0132d3527aa836 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -433,6 +433,25 @@ function,PyModule_New,3.2,, function,PyModule_NewObject,3.7,, function,PyModule_SetDocString,3.7,, var,PyModule_Type,3.2,, +function,PyMonitoring_EnterScope,3.13,, +function,PyMonitoring_ExitScope,3.13,, +function,PyMonitoring_FireBranchEvent,3.13,, +function,PyMonitoring_FireCRaiseEvent,3.13,, +function,PyMonitoring_FireCReturnEvent,3.13,, +function,PyMonitoring_FireCallEvent,3.13,, +function,PyMonitoring_FireExceptionHandledEvent,3.13,, +function,PyMonitoring_FireInstructionEvent,3.13,, +function,PyMonitoring_FireJumpEvent,3.13,, +function,PyMonitoring_FireLineEvent,3.13,, +function,PyMonitoring_FirePyResumeEvent,3.13,, +function,PyMonitoring_FirePyReturnEvent,3.13,, +function,PyMonitoring_FirePyStartEvent,3.13,, +function,PyMonitoring_FirePyThrowEvent,3.13,, +function,PyMonitoring_FirePyUnwindEvent,3.13,, +function,PyMonitoring_FirePyYieldEvent,3.13,, +function,PyMonitoring_FireRaiseEvent,3.13,, +function,PyMonitoring_FireReraiseEvent,3.13,, +function,PyMonitoring_FireStopIterationEvent,3.13,, function,PyNumber_Absolute,3.2,, function,PyNumber_Add,3.2,, function,PyNumber_And,3.2,, diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index d0e4f3c71c15e0..55f2646dffc046 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -464,6 +464,25 @@ def test_windows_feature_macros(self): "PyModule_NewObject", "PyModule_SetDocString", "PyModule_Type", + "PyMonitoring_EnterScope", + "PyMonitoring_ExitScope", + "PyMonitoring_FireBranchEvent", + "PyMonitoring_FireCRaiseEvent", + "PyMonitoring_FireCReturnEvent", + "PyMonitoring_FireCallEvent", + "PyMonitoring_FireExceptionHandledEvent", + "PyMonitoring_FireInstructionEvent", + "PyMonitoring_FireJumpEvent", + "PyMonitoring_FireLineEvent", + "PyMonitoring_FirePyResumeEvent", + "PyMonitoring_FirePyReturnEvent", + "PyMonitoring_FirePyStartEvent", + "PyMonitoring_FirePyThrowEvent", + "PyMonitoring_FirePyUnwindEvent", + "PyMonitoring_FirePyYieldEvent", + "PyMonitoring_FireRaiseEvent", + "PyMonitoring_FireReraiseEvent", + "PyMonitoring_FireStopIterationEvent", "PyNumber_Absolute", "PyNumber_Add", "PyNumber_And", diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 14dda7db1c323e..2ceea2b81cdeae 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2506,3 +2506,43 @@ added = '3.13' [function.PyType_GetModuleByDef] added = '3.13' + +# Add API for Monitoring in Python 3.13 (https://github.com/python/cpython/issues/111997) +[function.PyMonitoring_EnterScope] + added = '3.13' +[function.PyMonitoring_ExitScope] + added = '3.13' +[function.PyMonitoring_FireBranchEvent] + added = '3.13' +[function.PyMonitoring_FireCRaiseEvent] + added = '3.13' +[function.PyMonitoring_FireCReturnEvent] + added = '3.13' +[function.PyMonitoring_FireCallEvent] + added = '3.13' +[function.PyMonitoring_FireExceptionHandledEvent] + added = '3.13' +[function.PyMonitoring_FireInstructionEvent] + added = '3.13' +[function.PyMonitoring_FireJumpEvent] + added = '3.13' +[function.PyMonitoring_FireLineEvent] + added = '3.13' +[function.PyMonitoring_FirePyResumeEvent] + added = '3.13' +[function.PyMonitoring_FirePyReturnEvent] + added = '3.13' +[function.PyMonitoring_FirePyStartEvent] + added = '3.13' +[function.PyMonitoring_FirePyThrowEvent] + added = '3.13' +[function.PyMonitoring_FirePyUnwindEvent] + added = '3.13' +[function.PyMonitoring_FirePyYieldEvent] + added = '3.13' +[function.PyMonitoring_FireRaiseEvent] + added = '3.13' +[function.PyMonitoring_FireReraiseEvent] + added = '3.13' +[function.PyMonitoring_FireStopIterationEvent] + added = '3.13' diff --git a/PC/python3dll.c b/PC/python3dll.c index c6fdc0bd73b9fe..8223e98be206f6 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -409,6 +409,25 @@ EXPORT_FUNC(PyModule_New) EXPORT_FUNC(PyModule_NewObject) EXPORT_FUNC(PyModule_SetDocString) EXPORT_FUNC(PyModuleDef_Init) +EXPORT_FUNC(PyMonitoring_EnterScope) +EXPORT_FUNC(PyMonitoring_ExitScope) +EXPORT_FUNC(PyMonitoring_FireBranchEvent) +EXPORT_FUNC(PyMonitoring_FireCallEvent) +EXPORT_FUNC(PyMonitoring_FireCRaiseEvent) +EXPORT_FUNC(PyMonitoring_FireCReturnEvent) +EXPORT_FUNC(PyMonitoring_FireExceptionHandledEvent) +EXPORT_FUNC(PyMonitoring_FireInstructionEvent) +EXPORT_FUNC(PyMonitoring_FireJumpEvent) +EXPORT_FUNC(PyMonitoring_FireLineEvent) +EXPORT_FUNC(PyMonitoring_FirePyResumeEvent) +EXPORT_FUNC(PyMonitoring_FirePyReturnEvent) +EXPORT_FUNC(PyMonitoring_FirePyStartEvent) +EXPORT_FUNC(PyMonitoring_FirePyThrowEvent) +EXPORT_FUNC(PyMonitoring_FirePyUnwindEvent) +EXPORT_FUNC(PyMonitoring_FirePyYieldEvent) +EXPORT_FUNC(PyMonitoring_FireRaiseEvent) +EXPORT_FUNC(PyMonitoring_FireReraiseEvent) +EXPORT_FUNC(PyMonitoring_FireStopIterationEvent) EXPORT_FUNC(PyNumber_Absolute) EXPORT_FUNC(PyNumber_Add) EXPORT_FUNC(PyNumber_And) From 48176fc72ebf515ce6e8168054f475ca6e9d8810 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 27 Mar 2024 14:55:18 +0000 Subject: [PATCH 41/79] no need for two versions of EnterScope/ExitScope --- Include/monitoring.h | 13 ------------- Python/instrumentation.c | 15 ++------------- Python/pylifecycle-c98da669.o.tmp | 0 Python/pystate-0cb7e25d.o.tmp | 0 4 files changed, 2 insertions(+), 26 deletions(-) create mode 100644 Python/pylifecycle-c98da669.o.tmp create mode 100644 Python/pystate-0cb7e25d.o.tmp diff --git a/Include/monitoring.h b/Include/monitoring.h index 3e56f594790cb7..abf80087f3ff77 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -96,19 +96,6 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike } -static inline void -PyUnstable_Monitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) -{ - _PyMonitoring_EnterScope(state_array, version, event_types, length); -} - -static inline void -PyUnstable_Monitoring_ExitScope(void) -{ - _PyMonitoring_ExitScope(); -} - static inline int PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 40802a571af172..80f40f1769f17c 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2344,7 +2344,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs } void -_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -2361,7 +2361,7 @@ _PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, } void -_PyMonitoring_ExitScope(void) +PyMonitoring_ExitScope(void) { } @@ -2543,17 +2543,6 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik /******************* Public API *******************/ -void -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) -{ - _PyMonitoring_EnterScope(state_array, version, event_types, length); -} - -void -PyMonitoring_ExitScope(void) -{ -} #define IF_ACTIVE(STATE, X) \ if ((STATE)->active) { \ diff --git a/Python/pylifecycle-c98da669.o.tmp b/Python/pylifecycle-c98da669.o.tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Python/pystate-0cb7e25d.o.tmp b/Python/pystate-0cb7e25d.o.tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 From c52dddcb2c838401b9ca23488c4b46b9bb41e1c5 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 28 Mar 2024 11:29:59 +0000 Subject: [PATCH 42/79] Revert "update limited API" This reverts commit c0bcc2205e8038af91821bdbefcaf9c3090deabd. --- Doc/data/stable_abi.dat | 19 -------------- Lib/test/test_stable_abi_ctypes.py | 19 -------------- Misc/stable_abi.toml | 40 ------------------------------ PC/python3dll.c | 19 -------------- 4 files changed, 97 deletions(-) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 0132d3527aa836..2763bea5137cc7 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -433,25 +433,6 @@ function,PyModule_New,3.2,, function,PyModule_NewObject,3.7,, function,PyModule_SetDocString,3.7,, var,PyModule_Type,3.2,, -function,PyMonitoring_EnterScope,3.13,, -function,PyMonitoring_ExitScope,3.13,, -function,PyMonitoring_FireBranchEvent,3.13,, -function,PyMonitoring_FireCRaiseEvent,3.13,, -function,PyMonitoring_FireCReturnEvent,3.13,, -function,PyMonitoring_FireCallEvent,3.13,, -function,PyMonitoring_FireExceptionHandledEvent,3.13,, -function,PyMonitoring_FireInstructionEvent,3.13,, -function,PyMonitoring_FireJumpEvent,3.13,, -function,PyMonitoring_FireLineEvent,3.13,, -function,PyMonitoring_FirePyResumeEvent,3.13,, -function,PyMonitoring_FirePyReturnEvent,3.13,, -function,PyMonitoring_FirePyStartEvent,3.13,, -function,PyMonitoring_FirePyThrowEvent,3.13,, -function,PyMonitoring_FirePyUnwindEvent,3.13,, -function,PyMonitoring_FirePyYieldEvent,3.13,, -function,PyMonitoring_FireRaiseEvent,3.13,, -function,PyMonitoring_FireReraiseEvent,3.13,, -function,PyMonitoring_FireStopIterationEvent,3.13,, function,PyNumber_Absolute,3.2,, function,PyNumber_Add,3.2,, function,PyNumber_And,3.2,, diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 55f2646dffc046..d0e4f3c71c15e0 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -464,25 +464,6 @@ def test_windows_feature_macros(self): "PyModule_NewObject", "PyModule_SetDocString", "PyModule_Type", - "PyMonitoring_EnterScope", - "PyMonitoring_ExitScope", - "PyMonitoring_FireBranchEvent", - "PyMonitoring_FireCRaiseEvent", - "PyMonitoring_FireCReturnEvent", - "PyMonitoring_FireCallEvent", - "PyMonitoring_FireExceptionHandledEvent", - "PyMonitoring_FireInstructionEvent", - "PyMonitoring_FireJumpEvent", - "PyMonitoring_FireLineEvent", - "PyMonitoring_FirePyResumeEvent", - "PyMonitoring_FirePyReturnEvent", - "PyMonitoring_FirePyStartEvent", - "PyMonitoring_FirePyThrowEvent", - "PyMonitoring_FirePyUnwindEvent", - "PyMonitoring_FirePyYieldEvent", - "PyMonitoring_FireRaiseEvent", - "PyMonitoring_FireReraiseEvent", - "PyMonitoring_FireStopIterationEvent", "PyNumber_Absolute", "PyNumber_Add", "PyNumber_And", diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 2ceea2b81cdeae..14dda7db1c323e 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2506,43 +2506,3 @@ added = '3.13' [function.PyType_GetModuleByDef] added = '3.13' - -# Add API for Monitoring in Python 3.13 (https://github.com/python/cpython/issues/111997) -[function.PyMonitoring_EnterScope] - added = '3.13' -[function.PyMonitoring_ExitScope] - added = '3.13' -[function.PyMonitoring_FireBranchEvent] - added = '3.13' -[function.PyMonitoring_FireCRaiseEvent] - added = '3.13' -[function.PyMonitoring_FireCReturnEvent] - added = '3.13' -[function.PyMonitoring_FireCallEvent] - added = '3.13' -[function.PyMonitoring_FireExceptionHandledEvent] - added = '3.13' -[function.PyMonitoring_FireInstructionEvent] - added = '3.13' -[function.PyMonitoring_FireJumpEvent] - added = '3.13' -[function.PyMonitoring_FireLineEvent] - added = '3.13' -[function.PyMonitoring_FirePyResumeEvent] - added = '3.13' -[function.PyMonitoring_FirePyReturnEvent] - added = '3.13' -[function.PyMonitoring_FirePyStartEvent] - added = '3.13' -[function.PyMonitoring_FirePyThrowEvent] - added = '3.13' -[function.PyMonitoring_FirePyUnwindEvent] - added = '3.13' -[function.PyMonitoring_FirePyYieldEvent] - added = '3.13' -[function.PyMonitoring_FireRaiseEvent] - added = '3.13' -[function.PyMonitoring_FireReraiseEvent] - added = '3.13' -[function.PyMonitoring_FireStopIterationEvent] - added = '3.13' diff --git a/PC/python3dll.c b/PC/python3dll.c index 8223e98be206f6..c6fdc0bd73b9fe 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -409,25 +409,6 @@ EXPORT_FUNC(PyModule_New) EXPORT_FUNC(PyModule_NewObject) EXPORT_FUNC(PyModule_SetDocString) EXPORT_FUNC(PyModuleDef_Init) -EXPORT_FUNC(PyMonitoring_EnterScope) -EXPORT_FUNC(PyMonitoring_ExitScope) -EXPORT_FUNC(PyMonitoring_FireBranchEvent) -EXPORT_FUNC(PyMonitoring_FireCallEvent) -EXPORT_FUNC(PyMonitoring_FireCRaiseEvent) -EXPORT_FUNC(PyMonitoring_FireCReturnEvent) -EXPORT_FUNC(PyMonitoring_FireExceptionHandledEvent) -EXPORT_FUNC(PyMonitoring_FireInstructionEvent) -EXPORT_FUNC(PyMonitoring_FireJumpEvent) -EXPORT_FUNC(PyMonitoring_FireLineEvent) -EXPORT_FUNC(PyMonitoring_FirePyResumeEvent) -EXPORT_FUNC(PyMonitoring_FirePyReturnEvent) -EXPORT_FUNC(PyMonitoring_FirePyStartEvent) -EXPORT_FUNC(PyMonitoring_FirePyThrowEvent) -EXPORT_FUNC(PyMonitoring_FirePyUnwindEvent) -EXPORT_FUNC(PyMonitoring_FirePyYieldEvent) -EXPORT_FUNC(PyMonitoring_FireRaiseEvent) -EXPORT_FUNC(PyMonitoring_FireReraiseEvent) -EXPORT_FUNC(PyMonitoring_FireStopIterationEvent) EXPORT_FUNC(PyNumber_Absolute) EXPORT_FUNC(PyNumber_Add) EXPORT_FUNC(PyNumber_And) From 69cfe88f9a73a44b9a7d5ebfefc4a4b752d173c0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 28 Mar 2024 11:55:05 +0000 Subject: [PATCH 43/79] remove stable version. Rename Unstable functions --- Include/cpython/monitoring.h | 4 +- Include/monitoring.h | 132 +++++---------------- Lib/test/test_monitoring.py | 88 +++++++------- Modules/_testcapi/monitoring.c | 204 +++++++++------------------------ Python/instrumentation.c | 129 --------------------- 5 files changed, 126 insertions(+), 431 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 362fdf5e99ef80..b2e47b27c779a8 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -5,11 +5,11 @@ #ifndef Py_LIMITED_API PyAPI_FUNC(void) -_PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, +PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, uint32_t length); PyAPI_FUNC(void) -_PyMonitoring_ExitScope(void); +PyMonitoring_ExitScope(void); PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index abf80087f3ff77..0c3c42f797e87b 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -14,76 +14,6 @@ typedef struct _PyMonitoringState { # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H -PyAPI_FUNC(void) -PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); - -PyAPI_FUNC(void) -PyMonitoring_ExitScope(void); - -PyAPI_FUNC(int) -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - -PyAPI_FUNC(int) -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno); - -PyAPI_FUNC(int) -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - -PyAPI_FUNC(int) -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval); - -PyAPI_FUNC(int) -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); -PyAPI_FUNC(int) -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); - -PyAPI_FUNC(int) -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception); #ifndef Py_LIMITED_API @@ -97,7 +27,7 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike static inline int -PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -105,7 +35,7 @@ PyUnstable_Monitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -113,8 +43,8 @@ PyUnstable_Monitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -122,8 +52,8 @@ PyUnstable_Monitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -131,8 +61,8 @@ PyUnstable_Monitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) { _PYMONITORING_IF_ACTIVE( state, @@ -140,8 +70,8 @@ PyUnstable_Monitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) { _PYMONITORING_IF_ACTIVE( state, @@ -149,7 +79,7 @@ PyUnstable_Monitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) { _PYMONITORING_IF_ACTIVE( state, @@ -157,8 +87,8 @@ PyUnstable_Monitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *c } static inline int -PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( state, @@ -166,8 +96,8 @@ PyUnstable_Monitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike } static inline int -PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( state, @@ -175,8 +105,8 @@ PyUnstable_Monitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codeli } static inline int -PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) { _PYMONITORING_IF_ACTIVE( state, @@ -184,8 +114,8 @@ PyUnstable_Monitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -193,8 +123,8 @@ PyUnstable_Monitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -202,8 +132,8 @@ PyUnstable_Monitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelik } static inline int -PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -211,8 +141,8 @@ PyUnstable_Monitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -220,8 +150,8 @@ PyUnstable_Monitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObje } static inline int -PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -229,8 +159,8 @@ PyUnstable_Monitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codeli } static inline int -PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, @@ -238,8 +168,8 @@ PyUnstable_Monitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *code } static inline int -PyUnstable_Monitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) { _PYMONITORING_IF_ACTIVE( state, diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index d8a6286030c5de..0aff35bbc071a3 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1959,12 +1959,11 @@ def __call__(self, *args): def test_fire_event(self): for expected, event, function, *args in self.cases: - for unstable in (0, 1): - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with self.subTest(function.__name__, unstable=unstable): - args_ = (self.codelike, 0, unstable) + tuple(args) - self.check_event_count(event, function, args_, expected) + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args_ = (self.codelike, 0) + tuple(args) + self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } @@ -2006,46 +2005,43 @@ def check_disable(self, event, func, args, expected): def test_disable_event(self): for expected, event, function, *args in self.cases: - for unstable in (0, 1): - offset = 0 - self.codelike = _testcapi.CodeLike(2) - with self.subTest(function.__name__, unstable=unstable): - args_ = (self.codelike, 0, unstable) + tuple(args) - self.check_disable(event, function, args_, expected) + offset = 0 + self.codelike = _testcapi.CodeLike(2) + with self.subTest(function.__name__): + args_ = (self.codelike, 0) + tuple(args) + self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): - for unstable in (0,1): - with self.subTest(unstable=unstable): - try: - yield_counter = CounterWithDisable() - unwind_counter = CounterWithDisable() - sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) - sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) - sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) - - yield_value = int(math.log2(E.PY_YIELD)) - unwind_value = int(math.log2(E.PY_UNWIND)) - cl = _testcapi.CodeLike(2) - with self.Scope(cl, yield_value, unwind_value): - yield_counter.count = 0 - unwind_counter.count = 0 - - _testcapi.fire_event_py_unwind(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 0) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 1) - assert(unwind_counter.count == 1) - - yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) - - _testcapi.fire_event_py_yield(cl, 0, unstable, ValueError(42)) - assert(yield_counter.count == 2) - assert(unwind_counter.count == 1) + try: + yield_counter = CounterWithDisable() + unwind_counter = CounterWithDisable() + sys.monitoring.register_callback(TEST_TOOL, E.PY_YIELD, yield_counter) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, unwind_counter) + sys.monitoring.set_events(TEST_TOOL, E.PY_YIELD | E.PY_UNWIND) + + yield_value = int(math.log2(E.PY_YIELD)) + unwind_value = int(math.log2(E.PY_UNWIND)) + cl = _testcapi.CodeLike(2) + with self.Scope(cl, yield_value, unwind_value): + yield_counter.count = 0 + unwind_counter.count = 0 + + _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + assert(yield_counter.count == 0) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 1) + assert(unwind_counter.count == 1) + + yield_counter.disable = True + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) + + _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + assert(yield_counter.count == 2) + assert(unwind_counter.count == 1) - finally: - sys.monitoring.set_events(TEST_TOOL, 0) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 877cdb7245f802..e3c8ead8f68d2f 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -116,8 +116,8 @@ static PyObject * fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -125,13 +125,7 @@ fire_event_py_start(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyStartEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - } + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -139,8 +133,8 @@ static PyObject * fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -148,13 +142,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyResumeEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - } + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -162,9 +150,9 @@ static PyObject * fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -172,13 +160,7 @@ fire_event_py_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyReturnEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -186,9 +168,9 @@ static PyObject * fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -196,13 +178,7 @@ fire_event_c_return(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCReturnEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -210,9 +186,9 @@ static PyObject * fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -220,13 +196,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyYieldEvent(state, codelike, offset, retval); - } - else { - res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - } + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); RETURN_INT(res == -1 ? -1 : state->active); } @@ -234,9 +204,9 @@ static PyObject * fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiiOO", &codelike, &offset, &unstable, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } NULLABLE(arg0); @@ -245,13 +215,7 @@ fire_event_call(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCallEvent(state, codelike, offset, callable, arg0); - } - else { - res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - } + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); RETURN_INT(res == -1 ? -1 : state->active); } @@ -259,8 +223,8 @@ static PyObject * fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable, lineno; - if (!PyArg_ParseTuple(args, "Oiii", &codelike, &offset, &unstable, &lineno)) { + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -268,13 +232,7 @@ fire_event_line(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireLineEvent(state, codelike, offset, lineno); - } - else { - res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - } + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); RETURN_INT(res == -1 ? -1 : state->active); } @@ -282,8 +240,8 @@ static PyObject * fire_event_instruction(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &unstable)) { + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -291,13 +249,7 @@ fire_event_instruction(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireInstructionEvent(state, codelike, offset); - } - else { - res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - } + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -305,9 +257,9 @@ static PyObject * fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -315,13 +267,7 @@ fire_event_jump(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireJumpEvent(state, codelike, offset, target_offset); - } - else { - res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - } + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -329,9 +275,9 @@ static PyObject * fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } RAISE_UNLESS_CODELIKE(codelike); @@ -339,13 +285,7 @@ fire_event_branch(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireBranchEvent(state, codelike, offset, target_offset); - } - else { - res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - } + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); RETURN_INT(res == -1 ? -1 : state->active); } @@ -353,9 +293,9 @@ static PyObject * fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -364,13 +304,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyThrowEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -378,9 +312,9 @@ static PyObject * fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -389,13 +323,7 @@ fire_event_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireRaiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -403,9 +331,9 @@ static PyObject * fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -414,13 +342,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireCRaiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -428,9 +350,9 @@ static PyObject * fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -439,13 +361,7 @@ fire_event_reraise(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireReraiseEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -453,9 +369,9 @@ static PyObject * fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -464,13 +380,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -478,9 +388,9 @@ static PyObject * fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -489,13 +399,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FirePyUnwindEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } @@ -503,9 +407,9 @@ static PyObject * fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; - int offset, unstable; + int offset; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiiO", &codelike, &offset, &unstable, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); @@ -514,13 +418,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - int res; - if (unstable) { - res = PyUnstable_Monitoring_FireStopIterationEvent(state, codelike, offset, exception); - } - else { - res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - } + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); RETURN_INT(res == -1 ? -1 : state->active); } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 80f40f1769f17c..1199b03307284a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2540,132 +2540,3 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik return capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); } - -/******************* Public API *******************/ - - -#define IF_ACTIVE(STATE, X) \ - if ((STATE)->active) { \ - return (X); \ - } \ - else { \ - return 0; \ - } - -int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyStartEvent(state, codelike, offset)); -} - -int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); -} - -int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - IF_ACTIVE(state, _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} - -int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) -{ - IF_ACTIVE(state, _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); -} - -int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - -int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); -} - -int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - IF_ACTIVE(state, _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); -} - -int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - IF_ACTIVE(state, _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); -} - -int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); -} - -int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - IF_ACTIVE(state, _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); -} - -#undef IF_ACTIVE From 811402a693bbf7ccb42256e43ff0c614b937cd7d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:29:58 +0100 Subject: [PATCH 44/79] Delete Modules/_sqlite/connection-dd92fcfb.o.tmp --- Modules/_sqlite/connection-dd92fcfb.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Modules/_sqlite/connection-dd92fcfb.o.tmp diff --git a/Modules/_sqlite/connection-dd92fcfb.o.tmp b/Modules/_sqlite/connection-dd92fcfb.o.tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From 86d2f674ed0f0f4be9591d6932bc89ff22094cdd Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:30:18 +0100 Subject: [PATCH 45/79] Delete Modules/_testcapi/monitoring.c --- Modules/_testcapi/monitoring.c | 501 --------------------------------- 1 file changed, 501 deletions(-) delete mode 100644 Modules/_testcapi/monitoring.c diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c deleted file mode 100644 index e3c8ead8f68d2f..00000000000000 --- a/Modules/_testcapi/monitoring.c +++ /dev/null @@ -1,501 +0,0 @@ -#include "parts.h" -#include "util.h" - -#include "monitoring.h" - -#define Py_BUILD_CORE -#include "internal/pycore_instruments.h" - -typedef struct { - PyObject_HEAD - PyMonitoringState *monitoring_states; - uint64_t version; - int num_events; - /* Other fields */ -} PyCodeLikeObject; - - -static PyObject * -CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - int num_events; - if (!PyArg_ParseTuple(args, "i", &num_events)) { - return NULL; - } - PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( - num_events, sizeof(PyMonitoringState)); - if (states == NULL) { - return NULL; - } - PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); - if (self != NULL) { - self->version = 0; - self->monitoring_states = states; - self->num_events = num_events; - } - else { - PyMem_Free(states); - } - return (PyObject *) self; -} - -static void -CodeLike_dealloc(PyCodeLikeObject *self) -{ - if (self->monitoring_states) { - PyMem_Free(self->monitoring_states); - } - Py_TYPE(self)->tp_free((PyObject *) self); -} - -static PyObject * -CodeLike_str(PyCodeLikeObject *self) -{ - PyObject *res = NULL; - PyObject *sep = NULL; - PyObject *parts = NULL; - if (self->monitoring_states) { - parts = PyList_New(0); - if (parts == NULL) { - goto end; - } - - PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); - if (heading == NULL) { - goto end; - } - int err = PyList_Append(parts, heading); - Py_DECREF(heading); - if (err < 0) { - goto end; - } - - for (int i = 0; i < self->num_events; i++) { - PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); - if (part == NULL) { - goto end; - } - int err = PyList_Append(parts, part); - Py_XDECREF(part); - if (err < 0) { - goto end; - } - } - sep = PyUnicode_FromString(": "); - if (sep == NULL) { - goto end; - } - res = PyUnicode_Join(sep, parts); - } -end: - Py_XDECREF(sep); - Py_XDECREF(parts); - return res; -} - -static PyTypeObject PyCodeLike_Type = { - .ob_base = PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "monitoring.CodeLike", - .tp_doc = PyDoc_STR("CodeLike objects"), - .tp_basicsize = sizeof(PyCodeLikeObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = CodeLike_new, - .tp_dealloc = (destructor) CodeLike_dealloc, - .tp_str = (reprfunc) CodeLike_str, -}; - -#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ - PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ - return NULL; \ - } - -/*******************************************************************/ - -static PyObject * -fire_event_py_start(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_resume(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_c_return(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_yield(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_call(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { - return NULL; - } - NULLABLE(arg0); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_line(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_jump(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_branch(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_throw(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_c_raise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_reraise(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_exception_handled(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_py_unwind(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -static PyObject * -fire_event_stop_iteration(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { - return NULL; - } - NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); -} - -/*******************************************************************/ - -static PyObject * -enter_scope(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int event1, event2=0; - Py_ssize_t num_events = PyTuple_Size(args) - 1; - if (num_events == 1) { - if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { - return NULL; - } - } - else { - assert(num_events == 2); - if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { - return NULL; - } - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; - - uint8_t events[] = { event1, event2 }; - - PyMonitoring_EnterScope(cl->monitoring_states, - &cl->version, - events, - num_events); - - Py_RETURN_NONE; -} - -static PyObject * -exit_scope(PyObject *self, PyObject *args) -{ - PyMonitoring_ExitScope(); - Py_RETURN_NONE; -} - -static PyMethodDef TestMethods[] = { - {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, - {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, - {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, - {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, - {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, - {"fire_event_call", fire_event_call, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, - {"fire_event_line", fire_event_line, METH_VARARGS}, - {"fire_event_jump", fire_event_jump, METH_VARARGS}, - {"fire_event_branch", fire_event_branch, METH_VARARGS}, - {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, - {"fire_event_raise", fire_event_raise, METH_VARARGS}, - {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, - {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, - {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, - {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, - {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope", enter_scope, METH_VARARGS}, - {"exit_scope", exit_scope, METH_VARARGS}, - {NULL}, -}; - -int -_PyTestCapi_Init_Monitoring(PyObject *m) -{ - if (PyType_Ready(&PyCodeLike_Type) < 0) { - return -1; - } - if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { - Py_DECREF(m); - return -1; - } - if (PyModule_AddFunctions(m, TestMethods) < 0) { - return -1; - } - return 0; -} From e60f83f54d7cb73ead2a9e301294a7aea6f9fd1b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 1 Apr 2024 14:31:34 +0100 Subject: [PATCH 46/79] Revert "Delete Modules/_testcapi/monitoring.c" This reverts commit 86d2f674ed0f0f4be9591d6932bc89ff22094cdd. --- Modules/_testcapi/monitoring.c | 501 +++++++++++++++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 Modules/_testcapi/monitoring.c diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c new file mode 100644 index 00000000000000..e3c8ead8f68d2f --- /dev/null +++ b/Modules/_testcapi/monitoring.c @@ -0,0 +1,501 @@ +#include "parts.h" +#include "util.h" + +#include "monitoring.h" + +#define Py_BUILD_CORE +#include "internal/pycore_instruments.h" + +typedef struct { + PyObject_HEAD + PyMonitoringState *monitoring_states; + uint64_t version; + int num_events; + /* Other fields */ +} PyCodeLikeObject; + + +static PyObject * +CodeLike_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int num_events; + if (!PyArg_ParseTuple(args, "i", &num_events)) { + return NULL; + } + PyMonitoringState *states = (PyMonitoringState *)PyMem_Calloc( + num_events, sizeof(PyMonitoringState)); + if (states == NULL) { + return NULL; + } + PyCodeLikeObject *self = (PyCodeLikeObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->version = 0; + self->monitoring_states = states; + self->num_events = num_events; + } + else { + PyMem_Free(states); + } + return (PyObject *) self; +} + +static void +CodeLike_dealloc(PyCodeLikeObject *self) +{ + if (self->monitoring_states) { + PyMem_Free(self->monitoring_states); + } + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +CodeLike_str(PyCodeLikeObject *self) +{ + PyObject *res = NULL; + PyObject *sep = NULL; + PyObject *parts = NULL; + if (self->monitoring_states) { + parts = PyList_New(0); + if (parts == NULL) { + goto end; + } + + PyObject *heading = PyUnicode_FromString("PyCodeLikeObject"); + if (heading == NULL) { + goto end; + } + int err = PyList_Append(parts, heading); + Py_DECREF(heading); + if (err < 0) { + goto end; + } + + for (int i = 0; i < self->num_events; i++) { + PyObject *part = PyUnicode_FromFormat(" %d", self->monitoring_states[i].active); + if (part == NULL) { + goto end; + } + int err = PyList_Append(parts, part); + Py_XDECREF(part); + if (err < 0) { + goto end; + } + } + sep = PyUnicode_FromString(": "); + if (sep == NULL) { + goto end; + } + res = PyUnicode_Join(sep, parts); + } +end: + Py_XDECREF(sep); + Py_XDECREF(parts); + return res; +} + +static PyTypeObject PyCodeLike_Type = { + .ob_base = PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "monitoring.CodeLike", + .tp_doc = PyDoc_STR("CodeLike objects"), + .tp_basicsize = sizeof(PyCodeLikeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = CodeLike_new, + .tp_dealloc = (destructor) CodeLike_dealloc, + .tp_str = (reprfunc) CodeLike_str, +}; + +#define RAISE_UNLESS_CODELIKE(v) if (!Py_IS_TYPE((v), &PyCodeLike_Type)) { \ + PyErr_Format(PyExc_TypeError, "expected a code-like, got %s", Py_TYPE(v)->tp_name); \ + return NULL; \ + } + +/*******************************************************************/ + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_resume(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_c_return(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_yield(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *retval; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_call(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *callable, *arg0; + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + return NULL; + } + NULLABLE(arg0); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_line(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset, lineno; + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_instruction(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_jump(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_branch(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + return NULL; + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_throw(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_c_raise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_reraise(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_exception_handled(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_py_unwind(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +static PyObject * +fire_event_stop_iteration(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *exception; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + return NULL; + } + NULLABLE(exception); + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); + assert(offset >= 0 && offset < cl->num_events); + PyMonitoringState *state = &cl->monitoring_states[offset]; + + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); + RETURN_INT(res == -1 ? -1 : state->active); +} + +/*******************************************************************/ + +static PyObject * +enter_scope(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int event1, event2=0; + Py_ssize_t num_events = PyTuple_Size(args) - 1; + if (num_events == 1) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &event1)) { + return NULL; + } + } + else { + assert(num_events == 2); + if (!PyArg_ParseTuple(args, "Oii", &codelike, &event1, &event2)) { + return NULL; + } + } + RAISE_UNLESS_CODELIKE(codelike); + PyCodeLikeObject *cl = (PyCodeLikeObject *) codelike; + + uint8_t events[] = { event1, event2 }; + + PyMonitoring_EnterScope(cl->monitoring_states, + &cl->version, + events, + num_events); + + Py_RETURN_NONE; +} + +static PyObject * +exit_scope(PyObject *self, PyObject *args) +{ + PyMonitoring_ExitScope(); + Py_RETURN_NONE; +} + +static PyMethodDef TestMethods[] = { + {"fire_event_py_start", fire_event_py_start, METH_VARARGS}, + {"fire_event_py_resume", fire_event_py_resume, METH_VARARGS}, + {"fire_event_py_return", fire_event_py_return, METH_VARARGS}, + {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, + {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, + {"fire_event_call", fire_event_call, METH_VARARGS}, + {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, + {"fire_event_line", fire_event_line, METH_VARARGS}, + {"fire_event_jump", fire_event_jump, METH_VARARGS}, + {"fire_event_branch", fire_event_branch, METH_VARARGS}, + {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, + {"fire_event_raise", fire_event_raise, METH_VARARGS}, + {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, + {"fire_event_reraise", fire_event_reraise, METH_VARARGS}, + {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, + {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, + {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, + {"enter_scope", enter_scope, METH_VARARGS}, + {"exit_scope", exit_scope, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Monitoring(PyObject *m) +{ + if (PyType_Ready(&PyCodeLike_Type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "CodeLike", (PyObject *) &PyCodeLike_Type) < 0) { + Py_DECREF(m); + return -1; + } + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} From 8c052d3c9994d12e959e5f1578c8da8579d2d106 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:32:03 +0100 Subject: [PATCH 47/79] Delete Modules/_sqlite/cursor-8e377591.o.tmp --- Modules/_sqlite/cursor-8e377591.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Modules/_sqlite/cursor-8e377591.o.tmp diff --git a/Modules/_sqlite/cursor-8e377591.o.tmp b/Modules/_sqlite/cursor-8e377591.o.tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From e2f9f2f5d7c2cd4f46435b26cdb1db63a0759b3d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:33:35 +0100 Subject: [PATCH 48/79] Delete Python/pylifecycle-c98da669.o.tmp --- Python/pylifecycle-c98da669.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Python/pylifecycle-c98da669.o.tmp diff --git a/Python/pylifecycle-c98da669.o.tmp b/Python/pylifecycle-c98da669.o.tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From 7b02a82f60cbf3c13837241f4376ca61dc110753 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:34:09 +0100 Subject: [PATCH 49/79] Delete Python/pystate-0cb7e25d.o.tmp --- Python/pystate-0cb7e25d.o.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Python/pystate-0cb7e25d.o.tmp diff --git a/Python/pystate-0cb7e25d.o.tmp b/Python/pystate-0cb7e25d.o.tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From 5fdce6386cc6a93fab2c22c43ccbb1e35d2be10f Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 4 Apr 2024 12:20:01 +0100 Subject: [PATCH 50/79] remove a few bits --- Include/cpython/monitoring.h | 11 ----------- Include/monitoring.h | 8 -------- Lib/test/test_monitoring.py | 1 - Modules/_testcapi/monitoring.c | 18 ------------------ Python/instrumentation.c | 10 ---------- 5 files changed, 48 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index b2e47b27c779a8..867c5101ec48d1 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -25,10 +25,6 @@ PyAPI_FUNC(int) _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *retval); -PyAPI_FUNC(int) -_PyMonitoring_FirePyCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0); - PyAPI_FUNC(int) _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject* callable, PyObject *arg0); @@ -37,13 +33,6 @@ PyAPI_FUNC(int) _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, int lineno); -PyAPI_FUNC(int) -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset); - -PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset); - PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset); diff --git a/Include/monitoring.h b/Include/monitoring.h index 0c3c42f797e87b..701080e50db412 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -78,14 +78,6 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); } -static inline int -PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireInstructionEvent(state, codelike, offset)); -} - static inline int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 0aff35bbc071a3..f29d9ef49439c2 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1918,7 +1918,6 @@ def setUp(self): ( 1, E.PY_YIELD, capi.fire_event_py_yield, 10), ( 1, E.PY_RETURN, capi.fire_event_py_return, 20), ( 2, E.CALL, capi.fire_event_call, callable, 40), - (10, E.INSTRUCTION, capi.fire_event_instruction), ( 1, E.JUMP, capi.fire_event_jump, 60), ( 1, E.BRANCH, capi.fire_event_branch, 70), ( 1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e3c8ead8f68d2f..b88e1477ee8c00 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -236,23 +236,6 @@ fire_event_line(PyObject *self, PyObject *args) RETURN_INT(res == -1 ? -1 : state->active); } -static PyObject * -fire_event_instruction(PyObject *self, PyObject *args) -{ - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { - return NULL; - } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - - int res = PyMonitoring_FireInstructionEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); -} - static PyObject * fire_event_jump(PyObject *self, PyObject *args) { @@ -468,7 +451,6 @@ static PyMethodDef TestMethods[] = { {"fire_event_c_return", fire_event_c_return, METH_VARARGS}, {"fire_event_py_yield", fire_event_py_yield, METH_VARARGS}, {"fire_event_call", fire_event_call, METH_VARARGS}, - {"fire_event_instruction", fire_event_instruction, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, {"fire_event_branch", fire_event_branch, METH_VARARGS}, diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1199b03307284a..e064d639878dbd 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2431,16 +2431,6 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of return res; } -int -_PyMonitoring_FireInstructionEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - assert(state->active); - PyObject *args[3] = { NULL, NULL, NULL }; - int res= capi_call_instrumentation(state, codelike, offset, args, 2, - PY_MONITORING_EVENT_INSTRUCTION); - return res; -} - int _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *target_offset) From 21537daa01b55de5bce0cbea2fa9709087fe5e05 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 4 Apr 2024 15:56:07 +0200 Subject: [PATCH 51/79] Move non-limited API to Include/cpython/ (#56) --- Include/cpython/monitoring.h | 161 +++++++++++++++++++++++++++++++++- Include/monitoring.h | 164 +---------------------------------- 2 files changed, 161 insertions(+), 164 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 867c5101ec48d1..e82073fa0fcc93 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,7 +2,12 @@ # error "this header file must not be included directly" #endif -#ifndef Py_LIMITED_API + +typedef struct _PyMonitoringState { + uint8_t active; + uint8_t opaque; +} PyMonitoringState; + PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, @@ -11,6 +16,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, PyAPI_FUNC(void) PyMonitoring_ExitScope(void); + PyAPI_FUNC(int) _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); @@ -73,4 +79,155 @@ PyAPI_FUNC(int) _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, PyObject *exception); -#endif + +#define _PYMONITORING_IF_ACTIVE(STATE, X) \ + if ((STATE)->active) { \ + return (X); \ + } \ + else { \ + return 0; \ + } + +static inline int +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyStartEvent(state, codelike, offset)); +} + +static inline int +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); +} + +static inline int +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject* callable, PyObject *arg0) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); +} + +static inline int +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, + int lineno) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); +} + +static inline int +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); +} + +static inline int +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *target_offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); +} + +static inline int +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *retval) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); +} + +static inline int +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); +} + +static inline int +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, + PyObject *exception) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); +} + +#undef _PYMONITORING_IF_ACTIVE diff --git a/Include/monitoring.h b/Include/monitoring.h index 701080e50db412..985f7f230e44e3 100644 --- a/Include/monitoring.h +++ b/Include/monitoring.h @@ -4,174 +4,14 @@ extern "C" { #endif -typedef struct _PyMonitoringState { - uint8_t active; - uint8_t opaque; -} PyMonitoringState; - +// There is currently no limited API for monitoring +#ifndef Py_LIMITED_API # define Py_CPYTHON_MONITORING_H # include "cpython/monitoring.h" # undef Py_CPYTHON_MONITORING_H - - -#ifndef Py_LIMITED_API - -#define _PYMONITORING_IF_ACTIVE(STATE, X) \ - if ((STATE)->active) { \ - return (X); \ - } \ - else { \ - return 0; \ - } - - -static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyStartEvent(state, codelike, offset)); -} - -static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyResumeEvent(state, codelike, offset)); -} - -static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject* callable, PyObject *arg0) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0)); -} - -static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, - int lineno) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireLineEvent(state, codelike, offset, lineno)); -} - -static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset)); -} - -static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *target_offset) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); -} - -static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *retval) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCReturnEvent(state, codelike, offset, retval)); -} - -static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); -} - -static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, - PyObject *exception) -{ - _PYMONITORING_IF_ACTIVE( - state, - _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); -} - -#undef _PYMONITORING_IF_ACTIVE #endif - #ifdef __cplusplus } #endif From aaea28e51e0fd23856f36ba3e22e8ca415a943cb Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 15:06:44 +0100 Subject: [PATCH 52/79] Petr's comments --- Include/cpython/monitoring.h | 2 +- Lib/test/test_monitoring.py | 4 ++-- Modules/_testcapi/monitoring.c | 4 ++-- Python/instrumentation.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index e82073fa0fcc93..23e07de68b0678 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -11,7 +11,7 @@ typedef struct _PyMonitoringState { PyAPI_FUNC(void) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length); + const uint8_t *event_types, Py_ssize_t length); PyAPI_FUNC(void) PyMonitoring_ExitScope(void); diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index bef1517b8004c5..3cff6dd582b0e7 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1900,10 +1900,10 @@ def __init__(self, *args): self.args = args def __enter__(self): - _testcapi.enter_scope(*self.args) + _testcapi.monitoring_enter_scope(*self.args) def __exit__(self, *args): - _testcapi.exit_scope() + _testcapi.monitoring_exit_scope() def setUp(self): super(TestCApiEventGeneration, self).setUp() diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index b88e1477ee8c00..2af18828e3b63f 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -461,8 +461,8 @@ static PyMethodDef TestMethods[] = { {"fire_event_exception_handled", fire_event_exception_handled, METH_VARARGS}, {"fire_event_py_unwind", fire_event_py_unwind, METH_VARARGS}, {"fire_event_stop_iteration", fire_event_stop_iteration, METH_VARARGS}, - {"enter_scope", enter_scope, METH_VARARGS}, - {"exit_scope", exit_scope, METH_VARARGS}, + {"monitoring_enter_scope", enter_scope, METH_VARARGS}, + {"monitoring_exit_scope", exit_scope, METH_VARARGS}, {NULL}, }; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 4cc00a5a6df5a9..5819df9144576a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2345,7 +2345,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs void PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, - const uint8_t *event_types, uint32_t length) + const uint8_t *event_types, Py_ssize_t length) { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { @@ -2353,7 +2353,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, } _Py_GlobalMonitors *m = &interp->monitors; - for (uint32_t i = 0; i < length; i++) { + for (Py_ssize_t i = 0; i < length; i++) { int event = event_types[i]; state_array[i].active = m->tools[event]; } From 2f0a4d1f7beb0b75c591a0c6cd7944a6c692e78b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 16:55:05 +0100 Subject: [PATCH 53/79] int -> int32_t for offset --- Include/cpython/monitoring.h | 64 ++++++++++++++++++------------------ Python/instrumentation.c | 30 ++++++++--------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 23e07de68b0678..2b0be30a855da1 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -18,65 +18,65 @@ PyMonitoring_ExitScope(void); PyAPI_FUNC(int) -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset); +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset); +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0); PyAPI_FUNC(int) -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno); PyAPI_FUNC(int) -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); PyAPI_FUNC(int) -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception); @@ -89,7 +89,7 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik } static inline int -PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, @@ -97,7 +97,7 @@ PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, @@ -105,7 +105,7 @@ PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -114,7 +114,7 @@ PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -123,7 +123,7 @@ PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) { _PYMONITORING_IF_ACTIVE( @@ -132,7 +132,7 @@ PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) { _PYMONITORING_IF_ACTIVE( @@ -141,7 +141,7 @@ PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( @@ -150,7 +150,7 @@ PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int off } static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( @@ -159,7 +159,7 @@ PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int o } static inline int -PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { _PYMONITORING_IF_ACTIVE( @@ -168,7 +168,7 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -177,7 +177,7 @@ PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -186,7 +186,7 @@ PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int of } static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -195,7 +195,7 @@ PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -204,7 +204,7 @@ PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codel } static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -213,7 +213,7 @@ PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o } static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( @@ -222,7 +222,7 @@ PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int } static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { _PYMONITORING_IF_ACTIVE( diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5819df9144576a..191b121746d576 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2375,7 +2375,7 @@ _PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int offset) +_PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; @@ -2386,7 +2386,7 @@ _PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, in int -_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) { assert(state->active); @@ -2396,7 +2396,7 @@ _PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, in } int -_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) { assert(state->active); @@ -2406,7 +2406,7 @@ _PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) { assert(state->active); @@ -2416,7 +2416,7 @@ _PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) { assert(state->active); @@ -2432,7 +2432,7 @@ _PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { assert(state->active); @@ -2442,7 +2442,7 @@ _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int of } int -_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { assert(state->active); @@ -2452,7 +2452,7 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) { assert(state->active); @@ -2462,7 +2462,7 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2472,7 +2472,7 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2482,7 +2482,7 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int o } int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2492,7 +2492,7 @@ _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2502,7 +2502,7 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2512,7 +2512,7 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); @@ -2522,7 +2522,7 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int offset, +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) { assert(state->active); From 88e770f0138fb7258faedd9ff4ecb79007e3bc20 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 19:23:51 +0100 Subject: [PATCH 54/79] give EnterScope/ExitScope a return value --- Include/cpython/monitoring.h | 4 ++-- Python/instrumentation.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 2b0be30a855da1..b319d372940e72 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -9,11 +9,11 @@ typedef struct _PyMonitoringState { } PyMonitoringState; -PyAPI_FUNC(void) +PyAPI_FUNC(int) PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length); -PyAPI_FUNC(void) +PyAPI_FUNC(int) PyMonitoring_ExitScope(void); diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 191b121746d576..268840be83a647 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2343,7 +2343,7 @@ capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offs return err; } -void +int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) { @@ -2358,11 +2358,13 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, state_array[i].active = m->tools[event]; } *version = global_version(interp); + return 0; } -void +int PyMonitoring_ExitScope(void) { + return 0; } int From 2bed2e36d794de9ddb7e93d223ecee5d962fda38 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 10 Apr 2024 19:26:02 +0100 Subject: [PATCH 55/79] add doc --- Doc/c-api/index.rst | 1 + Doc/c-api/monitoring.rst | 124 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 Doc/c-api/monitoring.rst diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst index 9a8f1507b3f4cc..ba56b03c6ac8e7 100644 --- a/Doc/c-api/index.rst +++ b/Doc/c-api/index.rst @@ -25,3 +25,4 @@ document the API functions in detail. memory.rst objimpl.rst apiabiversion.rst + monitoring.rst diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst new file mode 100644 index 00000000000000..9f37bd57b0becc --- /dev/null +++ b/Doc/c-api/monitoring.rst @@ -0,0 +1,124 @@ +.. highlight:: c + +.. _monitoring: + +Added in version 3.13. + +An extension may need to interact with the event monitoring system. Subscribing +to events and registering callbacks can be done via the Python API exposed in +:mod:`sys.monitoring`. + +Generating Execution Events +=========================== + +The functions below make it possible for an extension to fire monitoring +events as it emulates the execution of Python code. Each of these functions +accepts a ``PyMonitoringState`` struct which contains concise information +about the activation state of events, as well as the event arguments, which +include a ``PyObject*`` representing the code object, the instruction offset +and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` +for details about the signatures of the different event callbacks). + +All of the functions below return 0 on success and -1 on error. + +.. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) + + Fire a ``PY_START`` event. + + +.. c:function:: int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) + + Fire a ``PY_RESUME`` event. + + +.. c:function:: int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) + + Fire a ``PY_RETURN`` event. + + +.. c:function:: int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* retval) + + Fire a ``PY_YIELD`` event. + + +.. c:function:: int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject* callable, PyObject *arg0) + + Fire a ``CALL`` event. + + +.. c:function:: int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno) + + Fire a ``LINE`` event. + + +.. c:function:: int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) + + Fire a ``JUMP`` event. + + +.. c:function:: int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) + + Fire a ``BRANCH`` event. + + +.. c:function:: int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) + + Fire a ``C_RETURN`` event. + + +.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``PY_THROW`` event. + + +.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``RAISE`` event. + + +.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``C_RAISE`` event. + + +.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``RERAISE`` event. + + +.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire an ``EXCEPTION_HANDLED`` event. + + +.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``PY_UNWIND`` event. + + +.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) + + Fire a ``STOP_ITERATION`` event. + + +Managing the Monitoring State +----------------------------- + +Monitoring states can be managed with the help of monitoring scopes. A scope +would typically correspond to a python function. + +.. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) + + Enter a monitoring scope. ``event_types`` is an array of the event IDs for + events that may be fired from the scope. For example, the ID of a ``PY_START`` + event is the value ``PY_MONITORING_EVENT_PY_START``. + ``state_array`` is an array with a monitoring state entry for each event in + ``event_types``, it is allocated by the user but populated by + ``PyMonitoring_EnterScope`` with information about the activation state of + the event. The size of ``event_types`` (and hence also of ``state_array``) + is given in ``length``. + + The ``version`` argument is a pointer to a value which should be initialized + to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this + function to determine whether event states have changed since the previous call, + and to return quickly if they have not. From 85e90333c179a588e6863dd832f31b565e696a95 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 10:53:55 +0100 Subject: [PATCH 56/79] fix typo --- Python/instrumentation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 268840be83a647..1820522c0ce607 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2349,7 +2349,7 @@ PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, { PyInterpreterState *interp = _PyInterpreterState_GET(); if (global_version(interp) == *version) { - return; + return 0; } _Py_GlobalMonitors *m = &interp->monitors; From 5162a039fac19a72227f1f67da30caaed69f4eff Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 11:30:40 +0100 Subject: [PATCH 57/79] update doc conf --- Doc/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/conf.py b/Doc/conf.py index f4c75c5758cb28..ed45d59f13b2a6 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -128,6 +128,7 @@ ('c:func', 'vsnprintf'), # Standard C types ('c:type', 'FILE'), + ('c:type', 'int32_t'), ('c:type', 'int64_t'), ('c:type', 'intmax_t'), ('c:type', 'off_t'), From 0438389caab87e4a8596130f8b750a0b29de1111 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 11:44:31 +0100 Subject: [PATCH 58/79] document PyMonitoringState --- Doc/c-api/monitoring.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 9f37bd57b0becc..d80ae942edd01d 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -19,6 +19,12 @@ include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). +.. c:type:: PyMonitoringState + + Representation of the state of an event type. It is allocated by the user + while its contents are maintained by the monitoring API functions described below. + + All of the functions below return 0 on success and -1 on error. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) From 75e51034603362d6aa04b970653b053a38f469c6 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:30:09 +0100 Subject: [PATCH 59/79] Update Doc/c-api/monitoring.rst Co-authored-by: Petr Viktorin --- Doc/c-api/monitoring.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index d80ae942edd01d..eafc74d915c560 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -25,7 +25,9 @@ for details about the signatures of the different event callbacks). while its contents are maintained by the monitoring API functions described below. -All of the functions below return 0 on success and -1 on error. +All of the functions below return 0 on success and -1 (with an exception set) on error. + +See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) From c7bd7f4d07a3be64ec6a5699f0e3ad03ece654ef Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 15:48:46 +0100 Subject: [PATCH 60/79] Petr's comments --- Include/cpython/monitoring.h | 31 ++++++++++++++++++++++++++ Include/internal/pycore_instruments.h | 32 --------------------------- Python/instrumentation.c | 4 ++-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index b319d372940e72..7a407f84310e3a 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -2,6 +2,37 @@ # error "this header file must not be included directly" #endif +/* Local events. + * These require bytecode instrumentation */ + +#define PY_MONITORING_EVENT_PY_START 0 +#define PY_MONITORING_EVENT_PY_RESUME 1 +#define PY_MONITORING_EVENT_PY_RETURN 2 +#define PY_MONITORING_EVENT_PY_YIELD 3 +#define PY_MONITORING_EVENT_CALL 4 +#define PY_MONITORING_EVENT_LINE 5 +#define PY_MONITORING_EVENT_INSTRUCTION 6 +#define PY_MONITORING_EVENT_JUMP 7 +#define PY_MONITORING_EVENT_BRANCH 8 +#define PY_MONITORING_EVENT_STOP_ITERATION 9 + +#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ + ((ev) < _PY_MONITORING_LOCAL_EVENTS) + +/* Other events, mainly exceptions */ + +#define PY_MONITORING_EVENT_RAISE 10 +#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11 +#define PY_MONITORING_EVENT_PY_UNWIND 12 +#define PY_MONITORING_EVENT_PY_THROW 13 +#define PY_MONITORING_EVENT_RERAISE 14 + + +/* Ancillary events */ + +#define PY_MONITORING_EVENT_C_RETURN 15 +#define PY_MONITORING_EVENT_C_RAISE 16 + typedef struct _PyMonitoringState { uint8_t active; diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 7f84d4a763bbcf..c98e82c8be5546 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -13,38 +13,6 @@ extern "C" { #define PY_MONITORING_TOOL_IDS 8 -/* Local events. - * These require bytecode instrumentation */ - -#define PY_MONITORING_EVENT_PY_START 0 -#define PY_MONITORING_EVENT_PY_RESUME 1 -#define PY_MONITORING_EVENT_PY_RETURN 2 -#define PY_MONITORING_EVENT_PY_YIELD 3 -#define PY_MONITORING_EVENT_CALL 4 -#define PY_MONITORING_EVENT_LINE 5 -#define PY_MONITORING_EVENT_INSTRUCTION 6 -#define PY_MONITORING_EVENT_JUMP 7 -#define PY_MONITORING_EVENT_BRANCH 8 -#define PY_MONITORING_EVENT_STOP_ITERATION 9 - -#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ - ((ev) < _PY_MONITORING_LOCAL_EVENTS) - -/* Other events, mainly exceptions */ - -#define PY_MONITORING_EVENT_RAISE 10 -#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11 -#define PY_MONITORING_EVENT_PY_UNWIND 12 -#define PY_MONITORING_EVENT_PY_THROW 13 -#define PY_MONITORING_EVENT_RERAISE 14 - - -/* Ancillary events */ - -#define PY_MONITORING_EVENT_C_RETURN 15 -#define PY_MONITORING_EVENT_C_RAISE 16 - - typedef uint32_t _PyMonitoringEventSet; /* Tool IDs */ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 1820522c0ce607..36ac7f0cb07ca0 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2287,7 +2287,7 @@ PyObject *_Py_CreateMonitoringObject(void) static int -capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int offset, +capi_call_instrumentation(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject **args, Py_ssize_t nargs, int event) { PyThreadState *tstate = _PyThreadState_GET(); @@ -2368,7 +2368,7 @@ PyMonitoring_ExitScope(void) } int -_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int offset) +_PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); PyObject *args[3] = { NULL, NULL, NULL }; From 2c09788aacbdf28172ad361e8e1f759017250dfc Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 16:28:54 +0100 Subject: [PATCH 61/79] update docs --- Doc/c-api/monitoring.rst | 10 +++++++++- Doc/library/sys.monitoring.rst | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index eafc74d915c560..78502f2e7a85dd 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -18,6 +18,8 @@ about the activation state of events, as well as the event arguments, which include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). +The ``codelike`` argument should be an instance of :class:`types.CodeType` +or of a type that emulates it. .. c:type:: PyMonitoringState @@ -119,7 +121,8 @@ would typically correspond to a python function. Enter a monitoring scope. ``event_types`` is an array of the event IDs for events that may be fired from the scope. For example, the ID of a ``PY_START`` - event is the value ``PY_MONITORING_EVENT_PY_START``. + event is the value ``PY_MONITORING_EVENT_PY_START``, which is numerically equal + to the base-2 logarithm of ``sys.monitoring.events.PY_START``. ``state_array`` is an array with a monitoring state entry for each event in ``event_types``, it is allocated by the user but populated by ``PyMonitoring_EnterScope`` with information about the activation state of @@ -130,3 +133,8 @@ would typically correspond to a python function. to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, and to return quickly if they have not. + + +.. :c:function:: int PyMonitoring_ExitScope(void) + + Exit the last scope that was entered with :c:function:`PyMonitoring_EnterScope`. diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 4980227c60b21e..3b8674d690db4c 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -255,7 +255,10 @@ No events are active by default. Per code object events '''''''''''''''''''''' -Events can also be controlled on a per code object basis. +Events can also be controlled on a per code object basis. The functions +defined below which accept a :class:`types.CodeType` should be prepared +to accept a look-alike object from functions which are not defined +in Python (see :c:`_monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From 5936200816195b7268787c2176b310ddc3498e74 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 17:00:53 +0100 Subject: [PATCH 62/79] fix doc --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 78502f2e7a85dd..88870ecd13812e 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -137,4 +137,4 @@ would typically correspond to a python function. .. :c:function:: int PyMonitoring_ExitScope(void) - Exit the last scope that was entered with :c:function:`PyMonitoring_EnterScope`. + Exit the last scope that was entered with ``PyMonitoring_EnterScope``. From 3f924e44c3642a8a6d22446fde0fca18aa871ada Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:09:48 +0100 Subject: [PATCH 63/79] whitespace --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 88870ecd13812e..10fc1a0f3781c5 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -19,7 +19,7 @@ include a ``PyObject*`` representing the code object, the instruction offset and sometimes additional, event-specific arguments (see :mod:`sys.monitoring` for details about the signatures of the different event callbacks). The ``codelike`` argument should be an instance of :class:`types.CodeType` -or of a type that emulates it. +or of a type that emulates it. .. c:type:: PyMonitoringState From d42b7c8d267dbf71fed6013ff1b8cef2f7173e99 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:10:54 +0100 Subject: [PATCH 64/79] fix doc ref --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 3b8674d690db4c..62885408c2a23d 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -258,7 +258,7 @@ Per code object events Events can also be controlled on a per code object basis. The functions defined below which accept a :class:`types.CodeType` should be prepared to accept a look-alike object from functions which are not defined -in Python (see :c:`_monitoring`). +in Python (see :ref:`_monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From d3a5dd596e25dc7e1d4120b1c0c0325743d415ff Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:22:50 +0100 Subject: [PATCH 65/79] fix ref --- Doc/library/sys.monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 62885408c2a23d..0e0095e108e9c0 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -258,7 +258,7 @@ Per code object events Events can also be controlled on a per code object basis. The functions defined below which accept a :class:`types.CodeType` should be prepared to accept a look-alike object from functions which are not defined -in Python (see :ref:`_monitoring`). +in Python (see :ref:`monitoring`). .. function:: get_local_events(tool_id: int, code: CodeType, /) -> int From 0c4e65dcd940096117fc5ce5a432c139afcb940e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 11 Apr 2024 18:44:04 +0100 Subject: [PATCH 66/79] add title --- Doc/c-api/monitoring.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 10fc1a0f3781c5..e8f90f88ab765d 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -2,6 +2,9 @@ .. _monitoring: +Monitorong C API +================ + Added in version 3.13. An extension may need to interact with the event monitoring system. Subscribing From a59568b83717877da98b71ac8583f115209ee70e Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:36:28 +0100 Subject: [PATCH 67/79] doc update Co-authored-by: Mark Shannon --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index e8f90f88ab765d..f07839c6920ad5 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -122,7 +122,7 @@ would typically correspond to a python function. .. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length) - Enter a monitoring scope. ``event_types`` is an array of the event IDs for + Enter a monitored scope. ``event_types`` is an array of the event IDs for events that may be fired from the scope. For example, the ID of a ``PY_START`` event is the value ``PY_MONITORING_EVENT_PY_START``, which is numerically equal to the base-2 logarithm of ``sys.monitoring.events.PY_START``. From 262977f137b57490a6b88713d4f2e35766a44304 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 18 Apr 2024 22:26:11 +0100 Subject: [PATCH 68/79] update doc per Petr's comments --- Doc/c-api/monitoring.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index f07839c6920ad5..b894aca3530d84 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -137,6 +137,13 @@ would typically correspond to a python function. function to determine whether event states have changed since the previous call, and to return quickly if they have not. + The scopes referred to here are lexical scopes: a function, class or method. + ``PyMonitoring_EnterScope`` should be called whenever the lexical scope + entered. Scopes can be nested, reusing the same *state_array* and *version*, + in situations like when emulating a recursive Python function. When a code-like's + execution is paused, such as when emulating a generator, the scope needs to + be exited and re-entered. + .. :c:function:: int PyMonitoring_ExitScope(void) From 7d530b1a413767606fa68775b106fbed994e6b91 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:20:20 +0100 Subject: [PATCH 69/79] reentered Co-authored-by: Mark Shannon --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index b894aca3530d84..2da926f384d75c 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -139,7 +139,7 @@ would typically correspond to a python function. The scopes referred to here are lexical scopes: a function, class or method. ``PyMonitoring_EnterScope`` should be called whenever the lexical scope - entered. Scopes can be nested, reusing the same *state_array* and *version*, + entered. Scopes can be reentered, reusing the same *state_array* and *version*, in situations like when emulating a recursive Python function. When a code-like's execution is paused, such as when emulating a generator, the scope needs to be exited and re-entered. From 45a789583d31c6bd08ff8fec1756b6cfb55326ed Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:15:37 +0100 Subject: [PATCH 70/79] Apply suggestions from code review Co-authored-by: Petr Viktorin --- Doc/c-api/monitoring.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 2da926f384d75c..245dc1021b5692 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -32,6 +32,9 @@ or of a type that emulates it. All of the functions below return 0 on success and -1 (with an exception set) on error. +They should not be called with an exception set; you might want to wrap the +call in :c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`. + See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) @@ -132,13 +135,14 @@ would typically correspond to a python function. the event. The size of ``event_types`` (and hence also of ``state_array``) is given in ``length``. - The ``version`` argument is a pointer to a value which should be initialized - to 0 and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this + The ``version`` argument is a pointer to a value which should be allocated + by the user together with ``state_array`` and initialized to 0, + and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, and to return quickly if they have not. The scopes referred to here are lexical scopes: a function, class or method. - ``PyMonitoring_EnterScope`` should be called whenever the lexical scope + ``PyMonitoring_EnterScope`` should be called whenever the lexical scope is entered. Scopes can be reentered, reusing the same *state_array* and *version*, in situations like when emulating a recursive Python function. When a code-like's execution is paused, such as when emulating a generator, the scope needs to From cf9dfd09e9fd666ba10ff79488ca3e337a3bbf99 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 19 Apr 2024 12:48:05 +0100 Subject: [PATCH 71/79] whitespace --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 245dc1021b5692..e1301859ddf517 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -135,7 +135,7 @@ would typically correspond to a python function. the event. The size of ``event_types`` (and hence also of ``state_array``) is given in ``length``. - The ``version`` argument is a pointer to a value which should be allocated + The ``version`` argument is a pointer to a value which should be allocated by the user together with ``state_array`` and initialized to 0, and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this function to determine whether event states have changed since the previous call, From 3a6e583715edaf813ab1cb1cab1b18b2e63ce043 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 22 Apr 2024 19:42:06 +0100 Subject: [PATCH 72/79] add exceptions and disabling to doc --- Doc/c-api/monitoring.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index e1301859ddf517..c733d80ab3d874 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -24,6 +24,12 @@ for details about the signatures of the different event callbacks). The ``codelike`` argument should be an instance of :class:`types.CodeType` or of a type that emulates it. +The VM disables tracing when firing an event, so there is no need for user +code to do that. + +It is expected that monitoring functions are not called with an exception set, +except for those which are firing exception-related events. + .. c:type:: PyMonitoringState Representation of the state of an event type. It is allocated by the user From a704c4a88f3f4c11b3e84bb2fd98a2fcdfb3254a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 26 Apr 2024 13:40:49 +0100 Subject: [PATCH 73/79] VM takes care of exception state for exception-related events --- Lib/test/test_monitoring.py | 29 +++- Modules/_testcapi/monitoring.c | 256 ++++++++++++++++++--------------- Python/instrumentation.c | 70 +++++++-- 3 files changed, 222 insertions(+), 133 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 3cff6dd582b0e7..f656613edb8f5f 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1928,6 +1928,7 @@ def setUp(self): ( 1, E.STOP_ITERATION, capi.fire_event_stop_iteration, ValueError(7)), ] + def check_event_count(self, event, func, args, expected): class Counter: def __init__(self): @@ -1961,8 +1962,23 @@ def test_fire_event(self): for expected, event, function, *args in self.cases: offset = 0 self.codelike = _testcapi.CodeLike(1) + with_exc = False + with self.subTest(function.__name__): + args_ = (self.codelike, offset, with_exc) + tuple(args) + self.check_event_count(event, function, args_, expected) + + EXCEPTION_EVENTS = { E.PY_THROW, E.RAISE, E.EXCEPTION_HANDLED, + E.PY_UNWIND, E.STOP_ITERATION } + + def test_fire_event_with_exc(self): + for expected, event, function, *args in self.cases: + if not event in self.EXCEPTION_EVENTS: + continue + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with_exc = True with self.subTest(function.__name__): - args_ = (self.codelike, 0) + tuple(args) + args_ = (self.codelike, offset, with_exc) + tuple(args) self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, @@ -2008,7 +2024,7 @@ def test_disable_event(self): offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - args_ = (self.codelike, 0) + tuple(args) + args_ = (self.codelike, 0, False) + tuple(args) self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): @@ -2022,24 +2038,25 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) + common_args = (cl, 0, False) with self.Scope(cl, yield_value, unwind_value): yield_counter.count = 0 unwind_counter.count = 0 - _testcapi.fire_event_py_unwind(cl, 0, ValueError(42)) + _testcapi.fire_event_py_unwind(*common_args, ValueError(42)) assert(yield_counter.count == 0) assert(unwind_counter.count == 1) - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 1) assert(unwind_counter.count == 1) yield_counter.disable = True - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 2) assert(unwind_counter.count == 1) - _testcapi.fire_event_py_yield(cl, 0, ValueError(42)) + _testcapi.fire_event_py_yield(*common_args, ValueError(42)) assert(yield_counter.count == 2) assert(unwind_counter.count == 1) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 2af18828e3b63f..7df04697f54eb3 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -112,21 +112,52 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ -static PyObject * -fire_event_py_start(PyObject *self, PyObject *args) +static PyMonitoringState * +setup_fire(PyObject *codelike, int offset, bool with_exc) { - PyObject *codelike; - int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { + PyErr_Format(PyExc_TypeError, + "expected a code-like, got %s", + Py_TYPE(codelike)->tp_name); return NULL; } - RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; + if (with_exc) { + PyErr_SetObject(PyExc_ValueError, Py_None); + } + return state; +} + +static int +teardown_fire(int res, PyMonitoringState *state, bool with_exc) +{ + if (res == -1) { + return -1; + } + if (with_exc) { + PyErr_Clear(); + } + return state->active; +} + +static PyObject * +fire_event_py_start(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + bool with_exc; + if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -134,16 +165,16 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { + bool with_exc; + if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -151,17 +182,17 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -169,17 +200,17 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -187,17 +218,17 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -205,18 +236,17 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - NULLABLE(arg0); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -224,16 +254,16 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { + bool with_exc; + if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -241,17 +271,17 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -259,17 +289,17 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + return NULL; + } + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { return NULL; } - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -277,18 +307,18 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -296,18 +326,18 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -315,18 +345,18 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -334,18 +364,18 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -353,18 +383,18 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -372,18 +402,18 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } static PyObject * @@ -391,18 +421,18 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; + bool with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { + if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; } NULLABLE(exception); - RAISE_UNLESS_CODELIKE(codelike); - PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); - assert(offset >= 0 && offset < cl->num_events); - PyMonitoringState *state = &cl->monitoring_states[offset]; - + PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + if (state == NULL) { + return NULL; + } int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(res == -1 ? -1 : state->active); + RETURN_INT(teardown_fire(res, state, with_exc)); } /*******************************************************************/ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index f36d3be04b05be..3d80c1aeefe429 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2569,9 +2569,15 @@ _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2579,9 +2585,15 @@ _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32 PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2589,9 +2601,15 @@ _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int3 PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_C_RAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_C_RAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2599,9 +2617,15 @@ _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RERAISE); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_RERAISE); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2609,9 +2633,15 @@ _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *code PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_EXCEPTION_HANDLED); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_EXCEPTION_HANDLED); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2619,9 +2649,15 @@ _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, in PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_UNWIND); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_UNWIND); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } int @@ -2629,7 +2665,13 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik PyObject *exception) { assert(state->active); + PyObject *exc = PyErr_GetRaisedException(); + PyObject *args[4] = { NULL, NULL, NULL, exception }; - return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_STOP_ITERATION); + int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_STOP_ITERATION); + if (res >= 0) { + PyErr_SetRaisedException(exc); + } + return res; } From c7de6096130ac37a7734292da7e39164aa74c070 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 26 Apr 2024 14:36:48 +0100 Subject: [PATCH 74/79] bool -> int --- Modules/_testcapi/monitoring.c | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 7df04697f54eb3..590511781507be 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -113,7 +113,7 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ static PyMonitoringState * -setup_fire(PyObject *codelike, int offset, bool with_exc) +setup_fire(PyObject *codelike, int offset, int with_exc) { if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { PyErr_Format(PyExc_TypeError, @@ -132,7 +132,7 @@ setup_fire(PyObject *codelike, int offset, bool with_exc) } static int -teardown_fire(int res, PyMonitoringState *state, bool with_exc) +teardown_fire(int res, PyMonitoringState *state, int with_exc) { if (res == -1) { return -1; @@ -148,7 +148,7 @@ fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { return NULL; } @@ -165,7 +165,7 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { return NULL; } @@ -182,7 +182,7 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -200,7 +200,7 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -218,7 +218,7 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *retval; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { return NULL; @@ -236,7 +236,7 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *callable, *arg0; if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { return NULL; @@ -254,7 +254,7 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - bool with_exc; + int with_exc; if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { return NULL; } @@ -271,7 +271,7 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { return NULL; @@ -289,7 +289,7 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *target_offset; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { return NULL; @@ -307,7 +307,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -326,7 +326,7 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -345,7 +345,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -364,7 +364,7 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -383,7 +383,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -402,7 +402,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; @@ -421,7 +421,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - bool with_exc; + int with_exc; PyObject *exception; if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { return NULL; From e673b5aaa28ca4a8496635fed6efa913d0db9b43 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 28 Apr 2024 16:28:19 +0100 Subject: [PATCH 75/79] exception events use 'current exception' --- Include/cpython/monitoring.h | 56 +++++-------- Lib/test/test_monitoring.py | 21 +---- Modules/_testcapi/monitoring.c | 138 ++++++++++++++------------------- Python/instrumentation.c | 123 +++++++++++++---------------- 4 files changed, 138 insertions(+), 200 deletions(-) diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 7a407f84310e3a..efb9ec0e587552 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -83,32 +83,25 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PyObject *retval); PyAPI_FUNC(int) -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); PyAPI_FUNC(int) -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception); +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset); #define _PYMONITORING_IF_ACTIVE(STATE, X) \ @@ -199,66 +192,59 @@ PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int3 } static inline int -PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception)); + _PyMonitoring_FirePyThrowEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireRaiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireReraiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireReraiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception)); + _PyMonitoring_FireExceptionHandledEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception)); + _PyMonitoring_FireCRaiseEvent(state, codelike, offset)); } static inline int -PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception)); + _PyMonitoring_FirePyUnwindEvent(state, codelike, offset)); } static inline int -PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception)); + _PyMonitoring_FireStopIterationEvent(state, codelike, offset)); } #undef _PYMONITORING_IF_ACTIVE diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index f656613edb8f5f..2192a4cc03a838 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1962,23 +1962,8 @@ def test_fire_event(self): for expected, event, function, *args in self.cases: offset = 0 self.codelike = _testcapi.CodeLike(1) - with_exc = False with self.subTest(function.__name__): - args_ = (self.codelike, offset, with_exc) + tuple(args) - self.check_event_count(event, function, args_, expected) - - EXCEPTION_EVENTS = { E.PY_THROW, E.RAISE, E.EXCEPTION_HANDLED, - E.PY_UNWIND, E.STOP_ITERATION } - - def test_fire_event_with_exc(self): - for expected, event, function, *args in self.cases: - if not event in self.EXCEPTION_EVENTS: - continue - offset = 0 - self.codelike = _testcapi.CodeLike(1) - with_exc = True - with self.subTest(function.__name__): - args_ = (self.codelike, offset, with_exc) + tuple(args) + args_ = (self.codelike, offset) + tuple(args) self.check_event_count(event, function, args_, expected) CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, @@ -2024,7 +2009,7 @@ def test_disable_event(self): offset = 0 self.codelike = _testcapi.CodeLike(2) with self.subTest(function.__name__): - args_ = (self.codelike, 0, False) + tuple(args) + args_ = (self.codelike, 0) + tuple(args) self.check_disable(event, function, args_, expected) def test_enter_scope_two_events(self): @@ -2038,7 +2023,7 @@ def test_enter_scope_two_events(self): yield_value = int(math.log2(E.PY_YIELD)) unwind_value = int(math.log2(E.PY_UNWIND)) cl = _testcapi.CodeLike(2) - common_args = (cl, 0, False) + common_args = (cl, 0) with self.Scope(cl, yield_value, unwind_value): yield_counter.count = 0 unwind_counter.count = 0 diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 590511781507be..e03987156528bc 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -113,7 +113,7 @@ static PyTypeObject PyCodeLike_Type = { /*******************************************************************/ static PyMonitoringState * -setup_fire(PyObject *codelike, int offset, int with_exc) +setup_fire(PyObject *codelike, int offset, PyObject *exc) { if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { PyErr_Format(PyExc_TypeError, @@ -125,21 +125,19 @@ setup_fire(PyObject *codelike, int offset, int with_exc) assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; - if (with_exc) { - PyErr_SetObject(PyExc_ValueError, Py_None); + if (exc != NULL) { + PyErr_SetRaisedException(Py_NewRef(exc)); } return state; } static int -teardown_fire(int res, PyMonitoringState *state, int with_exc) +teardown_fire(int res, PyMonitoringState *state) { if (res == -1) { return -1; } - if (with_exc) { - PyErr_Clear(); - } + PyErr_Clear(); return state->active; } @@ -148,16 +146,15 @@ fire_event_py_start(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; - if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -165,16 +162,15 @@ fire_event_py_resume(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; - if (!PyArg_ParseTuple(args, "Oip", &codelike, &offset, &with_exc)) { + if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -182,17 +178,16 @@ fire_event_py_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -200,17 +195,16 @@ fire_event_c_return(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -218,17 +212,16 @@ fire_event_py_yield(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *retval; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &retval)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -236,17 +229,16 @@ fire_event_call(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *callable, *arg0; - if (!PyArg_ParseTuple(args, "OipOO", &codelike, &offset, &with_exc, &callable, &arg0)) { + if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -254,16 +246,15 @@ fire_event_line(PyObject *self, PyObject *args) { PyObject *codelike; int offset, lineno; - int with_exc; - if (!PyArg_ParseTuple(args, "Oipi", &codelike, &offset, &with_exc, &lineno)) { + if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -271,17 +262,16 @@ fire_event_jump(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -289,17 +279,16 @@ fire_event_branch(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *target_offset; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &target_offset)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, NULL); if (state == NULL) { return NULL; } int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state, with_exc)); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -307,18 +296,17 @@ fire_event_py_throw(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -326,18 +314,17 @@ fire_event_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireRaiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireRaiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -345,18 +332,17 @@ fire_event_c_raise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -364,18 +350,17 @@ fire_event_reraise(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireReraiseEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireReraiseEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -383,18 +368,17 @@ fire_event_exception_handled(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -402,18 +386,17 @@ fire_event_py_unwind(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } static PyObject * @@ -421,18 +404,17 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) { PyObject *codelike; int offset; - int with_exc; PyObject *exception; - if (!PyArg_ParseTuple(args, "OipO", &codelike, &offset, &with_exc, &exception)) { + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &exception)) { return NULL; } NULLABLE(exception); - PyMonitoringState *state = setup_fire(codelike, offset, with_exc); + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } - int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset, exception); - RETURN_INT(teardown_fire(res, state, with_exc)); + int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset); + RETURN_INT(teardown_fire(res, state)); } /*******************************************************************/ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 3d80c1aeefe429..26fcec8c77c032 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2564,114 +2564,99 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_C_RETURN); } -int -_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) -{ - assert(state->active); +static inline PyObject * +exception_event_setup(void) { PyObject *exc = PyErr_GetRaisedException(); + assert(exc != NULL); + return exc; +} - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); - if (res >= 0) { + +static inline int +exception_event_teardown(int err, PyObject *exc) { + if (err == 0) { PyErr_SetRaisedException(exc); } - return res; + else { + assert(PyErr_Occurred()); + Py_DECREF(exc); + } + return err; } int -_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_PY_THROW); + return exception_event_teardown(err, exc); +} - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, +int +_PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) +{ + assert(state->active); + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_C_RAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_RERAISE); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_EXCEPTION_HANDLED); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_PY_UNWIND); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } int -_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, - PyObject *exception) +_PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { assert(state->active); - PyObject *exc = PyErr_GetRaisedException(); - - PyObject *args[4] = { NULL, NULL, NULL, exception }; - int res = capi_call_instrumentation(state, codelike, offset, args, 3, + PyObject *exc = exception_event_setup(); + PyObject *args[4] = { NULL, NULL, NULL, exc }; + int err = capi_call_instrumentation(state, codelike, offset, args, 3, PY_MONITORING_EVENT_STOP_ITERATION); - if (res >= 0) { - PyErr_SetRaisedException(exc); - } - return res; + return exception_event_teardown(err, exc); } From 5f00efbc15de4773136233f1e37d16ca6f7f9b78 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 28 Apr 2024 16:33:16 +0100 Subject: [PATCH 76/79] update doc --- Doc/c-api/monitoring.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index c733d80ab3d874..f1e7351978cc7e 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -28,7 +28,9 @@ The VM disables tracing when firing an event, so there is no need for user code to do that. It is expected that monitoring functions are not called with an exception set, -except for those which are firing exception-related events. +except for those which are firing exception-related events. In the latter case, +it is assumed that the event related to the current exception +(the one returned from :c:func:`PyErr_GetRaisedException`). .. c:type:: PyMonitoringState @@ -38,9 +40,6 @@ except for those which are firing exception-related events. All of the functions below return 0 on success and -1 (with an exception set) on error. -They should not be called with an exception set; you might want to wrap the -call in :c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`. - See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) @@ -88,37 +87,37 @@ See :mod:`sys.monitoring` for descriptions of the events. Fire a ``C_RETURN`` event. -.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``PY_THROW`` event. -.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``RAISE`` event. -.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``C_RAISE`` event. -.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``RERAISE`` event. -.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire an ``EXCEPTION_HANDLED`` event. -.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``PY_UNWIND`` event. -.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *exception) +.. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) Fire a ``STOP_ITERATION`` event. From 69e900ec35e6dd6ac97a2b93fd88ae6b2b57d161 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:08:48 +0100 Subject: [PATCH 77/79] raise on missing exception --- Lib/test/test_monitoring.py | 23 ++++++++++- Python/instrumentation.c | 78 ++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 2192a4cc03a838..66aaa09c2c9a03 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1946,8 +1946,14 @@ def __call__(self, *args): event_value = int(math.log2(event)) with self.Scope(self.codelike, event_value): counter.count = 0 - func(*args) - self.assertEqual(counter.count, expected) + try: + func(*args) + except ValueError as e: + self.assertIsInstance(expected, ValueError) + self.assertEqual(str(e), str(expected)) + return + else: + self.assertEqual(counter.count, expected) prev = sys.monitoring.register_callback(TEST_TOOL, event, None) with self.Scope(self.codelike, event_value): @@ -1966,6 +1972,19 @@ def test_fire_event(self): args_ = (self.codelike, offset) + tuple(args) self.check_event_count(event, function, args_, expected) + def test_missing_exception(self): + for _, event, function, *args in self.cases: + if not (args and isinstance(args[-1], BaseException)): + continue + offset = 0 + self.codelike = _testcapi.CodeLike(1) + with self.subTest(function.__name__): + args_ = (self.codelike, offset) + tuple(args[:-1]) + (None,) + evt = int(math.log2(event)) + expected = ValueError(f"Firing event {evt} with no exception set") + self.check_event_count(event, function, args_, expected) + + CANNOT_DISABLE = { E.PY_THROW, E.RAISE, E.RERAISE, E.EXCEPTION_HANDLED, E.PY_UNWIND } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 26fcec8c77c032..4d38c10690cc08 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2564,11 +2564,16 @@ _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int PY_MONITORING_EVENT_C_RETURN); } -static inline PyObject * -exception_event_setup(void) { - PyObject *exc = PyErr_GetRaisedException(); - assert(exc != NULL); - return exc; +static inline int +exception_event_setup(PyObject **exc, int event) { + *exc = PyErr_GetRaisedException(); + if (*exc == NULL) { + PyErr_Format(PyExc_ValueError, + "Firing event %d with no exception set", + event); + return -1; + } + return 0; } @@ -2587,76 +2592,97 @@ exception_event_teardown(int err, PyObject *exc) { int _PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_PY_THROW; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_THROW); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_RAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_C_RAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_C_RAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_RERAISE; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_RERAISE); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_EXCEPTION_HANDLED; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_EXCEPTION_HANDLED); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_PY_UNWIND; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_PY_UNWIND); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } int _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) { + int event = PY_MONITORING_EVENT_STOP_ITERATION; assert(state->active); - PyObject *exc = exception_event_setup(); + PyObject *exc; + if (exception_event_setup(&exc, event) < 0) { + return -1; + } PyObject *args[4] = { NULL, NULL, NULL, exc }; - int err = capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_STOP_ITERATION); + int err = capi_call_instrumentation(state, codelike, offset, args, 3, event); return exception_event_teardown(err, exc); } From 841eb6c09b6cd2ebbe9a174838fc3cf9d8587e6a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:09:34 +0100 Subject: [PATCH 78/79] typo in doc --- Doc/c-api/monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index f1e7351978cc7e..3f128a534962aa 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -29,7 +29,7 @@ code to do that. It is expected that monitoring functions are not called with an exception set, except for those which are firing exception-related events. In the latter case, -it is assumed that the event related to the current exception +it is assumed that the event relates to the current exception (the one returned from :c:func:`PyErr_GetRaisedException`). .. c:type:: PyMonitoringState From 2840f12a12f6738d5575f0820cac551eaca60686 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 29 Apr 2024 15:59:12 +0100 Subject: [PATCH 79/79] Petr's comments --- Doc/c-api/monitoring.rst | 27 +++++++----- Modules/_testcapi/monitoring.c | 76 ++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 3f128a534962aa..763ec8ef761e4e 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -27,10 +27,8 @@ or of a type that emulates it. The VM disables tracing when firing an event, so there is no need for user code to do that. -It is expected that monitoring functions are not called with an exception set, -except for those which are firing exception-related events. In the latter case, -it is assumed that the event relates to the current exception -(the one returned from :c:func:`PyErr_GetRaisedException`). +Monitoring functions should not be called with an exception set, +except those listed below as working with the current exception. .. c:type:: PyMonitoringState @@ -89,37 +87,44 @@ See :mod:`sys.monitoring` for descriptions of the events. .. c:function:: int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``PY_THROW`` event. + Fire a ``PY_THROW`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``RAISE`` event. + Fire a ``RAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``C_RAISE`` event. + Fire a ``C_RAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``RERAISE`` event. + Fire a ``RERAISE`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire an ``EXCEPTION_HANDLED`` event. + Fire an ``EXCEPTION_HANDLED`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``PY_UNWIND`` event. + Fire a ``PY_UNWIND`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). .. c:function:: int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset) - Fire a ``STOP_ITERATION`` event. + Fire a ``STOP_ITERATION`` event with the current exception (as returned by + :c:func:`PyErr_GetRaisedException`). Managing the Monitoring State diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index e03987156528bc..aa90cfc06c1536 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -115,12 +115,7 @@ static PyTypeObject PyCodeLike_Type = { static PyMonitoringState * setup_fire(PyObject *codelike, int offset, PyObject *exc) { - if (!Py_IS_TYPE(codelike, &PyCodeLike_Type)) { - PyErr_Format(PyExc_TypeError, - "expected a code-like, got %s", - Py_TYPE(codelike)->tp_name); - return NULL; - } + RAISE_UNLESS_CODELIKE(codelike); PyCodeLikeObject *cl = ((PyCodeLikeObject *)codelike); assert(offset >= 0 && offset < cl->num_events); PyMonitoringState *state = &cl->monitoring_states[offset]; @@ -132,11 +127,19 @@ setup_fire(PyObject *codelike, int offset, PyObject *exc) } static int -teardown_fire(int res, PyMonitoringState *state) +teardown_fire(int res, PyMonitoringState *state, PyObject *exception) { if (res == -1) { return -1; } + if (exception) { + assert(PyErr_Occurred()); + assert(((PyObject*)Py_TYPE(exception)) == PyErr_Occurred()); + } + + else { + assert(!PyErr_Occurred()); + } PyErr_Clear(); return state->active; } @@ -149,12 +152,13 @@ fire_event_py_start(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyStartEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -165,12 +169,13 @@ fire_event_py_resume(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oi", &codelike, &offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyResumeEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -182,12 +187,13 @@ fire_event_py_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -199,12 +205,13 @@ fire_event_c_return(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCReturnEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -216,12 +223,13 @@ fire_event_py_yield(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &retval)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FirePyYieldEvent(state, codelike, offset, retval); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -233,12 +241,13 @@ fire_event_call(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiOO", &codelike, &offset, &callable, &arg0)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireCallEvent(state, codelike, offset, callable, arg0); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -249,12 +258,13 @@ fire_event_line(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "Oii", &codelike, &offset, &lineno)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireLineEvent(state, codelike, offset, lineno); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -266,12 +276,13 @@ fire_event_jump(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireJumpEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -283,12 +294,13 @@ fire_event_branch(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { return NULL; } - PyMonitoringState *state = setup_fire(codelike, offset, NULL); + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); if (state == NULL) { return NULL; } int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -306,7 +318,7 @@ fire_event_py_throw(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FirePyThrowEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -324,7 +336,7 @@ fire_event_raise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireRaiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -342,7 +354,7 @@ fire_event_c_raise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireCRaiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -360,7 +372,7 @@ fire_event_reraise(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireReraiseEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -378,7 +390,7 @@ fire_event_exception_handled(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireExceptionHandledEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -396,7 +408,7 @@ fire_event_py_unwind(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FirePyUnwindEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } static PyObject * @@ -414,7 +426,7 @@ fire_event_stop_iteration(PyObject *self, PyObject *args) return NULL; } int res = PyMonitoring_FireStopIterationEvent(state, codelike, offset); - RETURN_INT(teardown_fire(res, state)); + RETURN_INT(teardown_fire(res, state, exception)); } /*******************************************************************/