Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
GH-103082: Implementation of PEP 669: Low Impact Monitoring for CPython#103083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
e85d910
6283ee8
4edb7b7
852c40b
416b314
7971979
9896902
f432a66
fb29b34
15a1ccd
9abb339
3ba6a39
aa09895
9e5d87d
e52cbe6
6c8be7e
c9e1e21
e52e8d3
f434ec7
b680084
e6e7cf1
5bbc83e
7fe9a43
8b9f996
9b02640
2cadf32
1f54d77
43a3f3e
3d436cf
691bcf5
f07be07
8b8f67e
d0a2228
2a3a85e
c3724ab
d64823c
284d0b1
b9e1f3b
1440473
825f42a
ce5ddb3
5740c47
da83abe
cdb2bda
0148fa3
c5fb4f4
7fa431b
25bbc61
5629a3e
477cc53
23b5f5e
dfc18c5
566adbe
cfb17ed
c535f76
d579d2e
0982e5e
0693423
d6453e5
0ee2aee
acdca93
f17ef14
e7f6c37
e44ebc5
ece51e6
e88921e
2d9f22c
b7579ac
5a089a6
d5fdec8
c88741d
b6744ca
6c3473a
899aecd
80d2e2e
94d35d8
5aa0805
b39edd3
c9c40cb
6611c72
50d28f1
7165f52
65c548e
575f7d1
415741d
d70a1a4
d580de6
2076d5f
7b32d79
662c16c
d0139e9
51a93e7
64bf37f
5faec77
0be1562
b32a075
85d6923
ebcc42f
7cfbc7e
d366364
fdb4860
aee722f
bba53b8
718fbc8
97ec1c5
edc6709
e40a68f
d9f8192
2d9a380
29f41e7
38b7f43
9a40dad
a551d65
4951306
44a031e
c2155b7
b218428
9c0429e
c6bf38e
82fe16c
43618a9
821ae52
505a08d
f63da91
c324344
168b34a
f07a080
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 { | ||
markshannon marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
/* 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 */ \ | ||
\ | ||
/* 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 */ \ | ||
/* 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. */ \ | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -58,12 +58,6 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *); | ||
#define PyTrace_C_RETURN 6 | ||
#define PyTrace_OPCODE 7 | ||
// Internal structure: you should not use it directly, but use public functions | ||
// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing(). | ||
typedef struct _PyCFrame { | ||
@@ -77,7 +71,6 @@ typedef struct _PyCFrame { | ||
* discipline and make sure that instances of this struct cannot | ||
* accessed outside of their lifetime. | ||
*/ | ||
/* Pointer to the currently executing frame (it can be NULL) */ | ||
struct _PyInterpreterFrame *current_frame; | ||
struct _PyCFrame *previous; | ||
@@ -157,7 +150,7 @@ struct _ts { | ||
This is to prevent the actual trace/profile code from being recorded in | ||
the trace/profile. */ | ||
int tracing; | ||
intwhat_event; /* The event currently beingmonitored, if any. */ | ||
markshannon marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
/* Pointer to current _PyCFrame in the C stack frame of the currently, | ||
* or most recently, executing _PyEval_EvalFrameDefault. */ | ||
@@ -228,8 +221,6 @@ struct _ts { | ||
/* Unique thread state id. */ | ||
uint64_t id; | ||
_PyStackChunk *datastack_chunk; | ||
PyObject **datastack_top; | ||
PyObject **datastack_limit; | ||
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -19,6 +19,7 @@ struct _frame { | ||||||||||||||
struct_PyInterpreterFrame*f_frame;/* points to the frame data */ | ||||||||||||||
PyObject*f_trace;/* Trace function */ | ||||||||||||||
intf_lineno;/* Current line number. Only valid if non-zero */ | ||||||||||||||
intf_last_traced_line;/* The last line traced for this frame */ | ||||||||||||||
charf_trace_lines;/* Emit per-line trace events? */ | ||||||||||||||
charf_trace_opcodes;/* Emit per-opcode trace events? */ | ||||||||||||||
charf_fast_as_locals;/* Have the fast locals of this frame been converted to a dict? */ | ||||||||||||||
@@ -137,10 +138,16 @@ _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame) | ||||||||||||||
returnframe->localsplus; | ||||||||||||||
} | ||||||||||||||
/* Fetches the stack pointer, and sets stacktop to -1. | ||||||||||||||
Having stacktop <= 0 ensures that invalid | ||||||||||||||
values are not visible to the cycle GC. | ||||||||||||||
We choose -1 rather than 0 to assist debugging. */ | ||||||||||||||
Comment on lines +142 to +144 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Suggested change
| ||||||||||||||
staticinlinePyObject** | ||||||||||||||
_PyFrame_GetStackPointer(_PyInterpreterFrame*frame) | ||||||||||||||
{ | ||||||||||||||
PyObject**sp=frame->localsplus+frame->stacktop; | ||||||||||||||
frame->stacktop=-1; | ||||||||||||||
returnsp; | ||||||||||||||
} | ||||||||||||||
staticinlinevoid | ||||||||||||||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#ifndef Py_INTERNAL_INSTRUMENT_H | ||
#define Py_INTERNAL_INSTRUMENT_H | ||
#include "pycore_bitutils.h" // _Py_popcount32 | ||
#include "pycore_frame.h" | ||
#include "cpython/code.h" | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
#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_INSTRUMENTED_EVENTS 10 | ||
/* 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 | ||
/* Ancilliary events */ | ||
#define PY_MONITORING_EVENT_C_RETURN 14 | ||
#define PY_MONITORING_EVENT_C_RAISE 15 | ||
typedef uint32_t _PyMonitoringEventSet; | ||
/* Tool IDs */ | ||
/* These are defined in PEP 669 for convenience to avoid clashes */ | ||
#define PY_MONITORING_DEBUGGER_ID 0 | ||
#define PY_MONITORING_COVERAGE_ID 1 | ||
#define PY_MONITORING_PROFILER_ID 2 | ||
#define PY_MONITORING_OPTIMIZER_ID 5 | ||
/* Internal IDs used to suuport sys.setprofile() and sys.settrace() */ | ||
#define PY_MONITORING_SYS_PROFILE_ID 6 | ||
#define PY_MONITORING_SYS_TRACE_ID 7 | ||
PyObject *_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj); | ||
int _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events); | ||
extern int | ||
_Py_call_instrumentation(PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr); | ||
extern int | ||
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, | ||
_Py_CODEUNIT *instr); | ||
extern int | ||
_Py_call_instrumentation_instruction( | ||
PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr); | ||
int | ||
_Py_call_instrumentation_jump( | ||
PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *target); | ||
extern int | ||
_Py_call_instrumentation_arg(PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg); | ||
extern int | ||
_Py_call_instrumentation_2args(PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); | ||
extern void | ||
_Py_call_instrumentation_exc0(PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr); | ||
extern void | ||
_Py_call_instrumentation_exc2(PyThreadState *tstate, int event, | ||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); | ||
extern int | ||
_Py_Instrumentation_GetLine(PyCodeObject *code, int index); | ||
extern PyObject _PyInstrumentation_MISSING; | ||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif /* !Py_INTERNAL_INSTRUMENT_H */ |
Uh oh!
There was an error while loading.Please reload this page.