GH-103082: Implementation of PEP 669: Low Impact Monitoring for CPython (GH-103083)

* The majority of the monitoring code is in instrumentation.c

* The new instrumentation bytecodes are in bytecodes.c

* legacy_tracing.c adapts the new API to the old sys.setrace and sys.setprofile APIs
This commit is contained in:
Mark Shannon 2023-04-12 12:04:55 +01:00 committed by GitHub
parent dce2d38cb0
commit 411b169281
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 6029 additions and 1625 deletions

View file

@ -3,10 +3,22 @@
#ifndef Py_LIMITED_API
#ifndef Py_CODE_H
#define Py_CODE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Count of all "real" monitoring events (not derived from other events) */
#define PY_MONITORING_UNGROUPED_EVENTS 14
/* Count of all monitoring events */
#define PY_MONITORING_EVENTS 16
/* Table of which tools are active for each monitored event. */
typedef struct _Py_Monitors {
uint8_t tools[PY_MONITORING_UNGROUPED_EVENTS];
} _Py_Monitors;
/* Each instruction in a code object is a fixed-width value,
* currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG
* opcode allows for larger values but the current limit is 3 uses
@ -56,6 +68,35 @@ typedef struct {
PyObject *_co_freevars;
} _PyCoCached;
/* Ancilliary data structure used for instrumentation.
Line instrumentation creates an array of
these. One entry per code unit.*/
typedef struct {
uint8_t original_opcode;
int8_t line_delta;
} _PyCoLineInstrumentationData;
/* Main data structure used for instrumentation.
* This is allocated when needed for instrumentation
*/
typedef struct {
/* Monitoring specific to this code object */
_Py_Monitors local_monitors;
/* Monitoring that is active on this code object */
_Py_Monitors active_monitors;
/* The tools that are to be notified for events for the matching code unit */
uint8_t *tools;
/* Information to support line events */
_PyCoLineInstrumentationData *lines;
/* The tools that are to be notified for line events for the matching code unit */
uint8_t *line_tools;
/* Information to support instruction events */
/* The underlying instructions, which can themselves be instrumented */
uint8_t *per_instruction_opcodes;
/* The tools that are to be notified for instruction events for the matching code unit */
uint8_t *per_instruction_tools;
} _PyCoMonitoringData;
// To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are
// defined in this macro:
#define _PyCode_DEF(SIZE) { \
@ -87,7 +128,6 @@ typedef struct {
PyObject *co_exceptiontable; /* Byte string encoding exception handling \
table */ \
int co_flags; /* CO_..., see below */ \
short _co_linearray_entry_size; /* Size of each entry in _co_linearray */ \
\
/* The rest are not so impactful on performance. */ \
int co_argcount; /* #arguments, except *args */ \
@ -114,8 +154,9 @@ typedef struct {
PyObject *co_linetable; /* bytes object that holds location info */ \
PyObject *co_weakreflist; /* to support weakrefs to code objects */ \
_PyCoCached *_co_cached; /* cached co_* attributes */ \
uint64_t _co_instrumentation_version; /* current instrumentation version */ \
_PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \
int _co_firsttraceable; /* index of first traceable instruction */ \
char *_co_linearray; /* array of line offsets */ \
/* Scratch space for extra data relating to the code object. \
Type is a void* to keep the format private in codeobject.c to force \
people to go through the proper APIs. */ \