summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-04-12 11:04:55 (GMT)
committerGitHub <noreply@github.com>2023-04-12 11:04:55 (GMT)
commit411b1692811b2ecac59cb0df0f920861c7cf179a (patch)
tree64f7234e9d35623565ff1bb7fbd2c4688e8d3774 /Include
parentdce2d38cb04b541bad477ccc1040a68fa70a9a69 (diff)
downloadcpython-411b1692811b2ecac59cb0df0f920861c7cf179a.zip
cpython-411b1692811b2ecac59cb0df0f920861c7cf179a.tar.gz
cpython-411b1692811b2ecac59cb0df0f920861c7cf179a.tar.bz2
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
Diffstat (limited to 'Include')
-rw-r--r--Include/cpython/code.h45
-rw-r--r--Include/cpython/pystate.h11
-rw-r--r--Include/internal/pycore_code.h30
-rw-r--r--Include/internal/pycore_frame.h9
-rw-r--r--Include/internal/pycore_instruments.h107
-rw-r--r--Include/internal/pycore_interp.h14
-rw-r--r--Include/internal/pycore_opcode.h133
-rw-r--r--Include/internal/pycore_pystate.h10
-rw-r--r--Include/opcode.h145
9 files changed, 325 insertions, 179 deletions
diff --git a/Include/cpython/code.h b/Include/cpython/code.h
index abcf125..6bead36 100644
--- a/Include/cpython/code.h
+++ b/Include/cpython/code.h
@@ -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. */ \
diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index 3efb241..ea6ed8d 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -58,12 +58,6 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
#define PyTrace_C_RETURN 6
#define PyTrace_OPCODE 7
-
-typedef struct {
- PyCodeObject *code; // The code object for the bounds. May be NULL.
- PyCodeAddressRange bounds; // Only valid if code != NULL.
-} PyTraceInfo;
-
// 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.
*/
- uint8_t use_tracing; // 0 or 255 (or'ed into opcode, hence 8-bit type)
/* 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;
- int tracing_what; /* The event currently being traced, if any. */
+ int what_event; /* The event currently being monitored, if any. */
/* 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;
- PyTraceInfo trace_info;
-
_PyStackChunk *datastack_chunk;
PyObject **datastack_top;
PyObject **datastack_limit;
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index faf1be5..d32f37a 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -441,32 +441,6 @@ adaptive_counter_backoff(uint16_t counter) {
/* Line array cache for tracing */
-extern int _PyCode_CreateLineArray(PyCodeObject *co);
-
-static inline int
-_PyCode_InitLineArray(PyCodeObject *co)
-{
- if (co->_co_linearray) {
- return 0;
- }
- return _PyCode_CreateLineArray(co);
-}
-
-static inline int
-_PyCode_LineNumberFromArray(PyCodeObject *co, int index)
-{
- assert(co->_co_linearray != NULL);
- assert(index >= 0);
- assert(index < Py_SIZE(co));
- if (co->_co_linearray_entry_size == 2) {
- return ((int16_t *)co->_co_linearray)[index];
- }
- else {
- assert(co->_co_linearray_entry_size == 4);
- return ((int32_t *)co->_co_linearray)[index];
- }
-}
-
typedef struct _PyShimCodeDef {
const uint8_t *code;
int codelen;
@@ -500,6 +474,10 @@ extern uint32_t _Py_next_func_version;
#define COMPARISON_NOT_EQUALS (COMPARISON_UNORDERED | COMPARISON_LESS_THAN | COMPARISON_GREATER_THAN)
+extern int _Py_Instrument(PyCodeObject *co, PyInterpreterState *interp);
+
+extern int _Py_GetBaseOpcode(PyCodeObject *code, int offset);
+
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 5806cf0..856297a 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -19,6 +19,7 @@ struct _frame {
struct _PyInterpreterFrame *f_frame; /* points to the frame data */
PyObject *f_trace; /* Trace function */
int f_lineno; /* Current line number. Only valid if non-zero */
+ int f_last_traced_line; /* The last line traced for this frame */
char f_trace_lines; /* Emit per-line trace events? */
char f_trace_opcodes; /* Emit per-opcode trace events? */
char f_fast_as_locals; /* Have the fast locals of this frame been converted to a dict? */
@@ -137,10 +138,16 @@ _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
return frame->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. */
static inline PyObject**
_PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
{
- return frame->localsplus+frame->stacktop;
+ PyObject **sp = frame->localsplus + frame->stacktop;
+ frame->stacktop = -1;
+ return sp;
}
static inline void
diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h
new file mode 100644
index 0000000..e94d875
--- /dev/null
+++ b/Include/internal/pycore_instruments.h
@@ -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 */
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index d64a68c..86ae3d8 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -24,6 +24,7 @@ extern "C" {
#include "pycore_genobject.h" // struct _Py_async_gen_state
#include "pycore_gc.h" // struct _gc_runtime_state
#include "pycore_import.h" // struct _import_state
+#include "pycore_instruments.h" // PY_MONITORING_EVENTS
#include "pycore_list.h" // struct _Py_list_state
#include "pycore_global_objects.h" // struct _Py_interp_static_objects
#include "pycore_object_state.h" // struct _py_object_state
@@ -37,7 +38,6 @@ struct _Py_long_state {
int max_str_digits;
};
-
/* interpreter state */
/* PyInterpreterState holds the global state for one of the runtime's
@@ -49,6 +49,9 @@ struct _is {
PyInterpreterState *next;
+ uint64_t monitoring_version;
+ uint64_t last_restart_version;
+
struct pythreads {
uint64_t next_unique_id;
/* The linked list of threads, newest first. */
@@ -148,6 +151,15 @@ struct _is {
struct callable_cache callable_cache;
PyCodeObject *interpreter_trampoline;
+ _Py_Monitors monitors;
+ bool f_opcode_trace_set;
+ bool sys_profile_initialized;
+ bool sys_trace_initialized;
+ Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */
+ Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */
+ PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][PY_MONITORING_EVENTS];
+ PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];
+
struct _Py_interp_cached_objects cached_objects;
struct _Py_interp_static_objects static_objects;
diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h
index f5e9176..c039d71 100644
--- a/Include/internal/pycore_opcode.h
+++ b/Include/internal/pycore_opcode.h
@@ -112,6 +112,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
[DICT_UPDATE] = DICT_UPDATE,
[END_ASYNC_FOR] = END_ASYNC_FOR,
[END_FOR] = END_FOR,
+ [END_SEND] = END_SEND,
[EXTENDED_ARG] = EXTENDED_ARG,
[FORMAT_VALUE] = FORMAT_VALUE,
[FOR_ITER] = FOR_ITER,
@@ -127,6 +128,23 @@ const uint8_t _PyOpcode_Deopt[256] = {
[GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER,
[IMPORT_FROM] = IMPORT_FROM,
[IMPORT_NAME] = IMPORT_NAME,
+ [INSTRUMENTED_CALL] = INSTRUMENTED_CALL,
+ [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,
+ [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR,
+ [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND,
+ [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER,
+ [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION,
+ [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,
+ [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,
+ [INSTRUMENTED_LINE] = INSTRUMENTED_LINE,
+ [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,
+ [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,
+ [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,
+ [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,
+ [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME,
+ [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST,
+ [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,
+ [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,
[INTERPRETER_EXIT] = INTERPRETER_EXIT,
[IS_OP] = IS_OP,
[JUMP_BACKWARD] = JUMP_BACKWARD,
@@ -179,6 +197,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
[PUSH_NULL] = PUSH_NULL,
[RAISE_VARARGS] = RAISE_VARARGS,
[RERAISE] = RERAISE,
+ [RESERVED] = RESERVED,
[RESUME] = RESUME,
[RETURN_CONST] = RETURN_CONST,
[RETURN_GENERATOR] = RETURN_GENERATOR,
@@ -223,17 +242,19 @@ static const char *const _PyOpcode_OpName[263] = {
[PUSH_NULL] = "PUSH_NULL",
[INTERPRETER_EXIT] = "INTERPRETER_EXIT",
[END_FOR] = "END_FOR",
+ [END_SEND] = "END_SEND",
[BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT",
[BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT",
[BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE",
- [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE",
[NOP] = "NOP",
- [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT",
+ [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE",
[UNARY_NEGATIVE] = "UNARY_NEGATIVE",
[UNARY_NOT] = "UNARY_NOT",
+ [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT",
[BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT",
- [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT",
[UNARY_INVERT] = "UNARY_INVERT",
+ [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT",
+ [RESERVED] = "RESERVED",
[BINARY_OP_SUBTRACT_INT] = "BINARY_OP_SUBTRACT_INT",
[BINARY_SUBSCR_DICT] = "BINARY_SUBSCR_DICT",
[BINARY_SUBSCR_GETITEM] = "BINARY_SUBSCR_GETITEM",
@@ -241,21 +262,21 @@ static const char *const _PyOpcode_OpName[263] = {
[BINARY_SUBSCR_TUPLE_INT] = "BINARY_SUBSCR_TUPLE_INT",
[CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS",
[CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS",
- [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS",
- [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS",
[BINARY_SUBSCR] = "BINARY_SUBSCR",
[BINARY_SLICE] = "BINARY_SLICE",
[STORE_SLICE] = "STORE_SLICE",
- [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS",
- [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
+ [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS",
+ [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS",
[GET_LEN] = "GET_LEN",
[MATCH_MAPPING] = "MATCH_MAPPING",
[MATCH_SEQUENCE] = "MATCH_SEQUENCE",
[MATCH_KEYS] = "MATCH_KEYS",
- [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST",
+ [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS",
[PUSH_EXC_INFO] = "PUSH_EXC_INFO",
[CHECK_EXC_MATCH] = "CHECK_EXC_MATCH",
[CHECK_EG_MATCH] = "CHECK_EG_MATCH",
+ [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
+ [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST",
[CALL_NO_KW_BUILTIN_O] = "CALL_NO_KW_BUILTIN_O",
[CALL_NO_KW_ISINSTANCE] = "CALL_NO_KW_ISINSTANCE",
[CALL_NO_KW_LEN] = "CALL_NO_KW_LEN",
@@ -265,8 +286,6 @@ static const char *const _PyOpcode_OpName[263] = {
[CALL_NO_KW_METHOD_DESCRIPTOR_O] = "CALL_NO_KW_METHOD_DESCRIPTOR_O",
[CALL_NO_KW_STR_1] = "CALL_NO_KW_STR_1",
[CALL_NO_KW_TUPLE_1] = "CALL_NO_KW_TUPLE_1",
- [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1",
- [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT",
[WITH_EXCEPT_START] = "WITH_EXCEPT_START",
[GET_AITER] = "GET_AITER",
[GET_ANEXT] = "GET_ANEXT",
@@ -274,39 +293,39 @@ static const char *const _PyOpcode_OpName[263] = {
[BEFORE_WITH] = "BEFORE_WITH",
[END_ASYNC_FOR] = "END_ASYNC_FOR",
[CLEANUP_THROW] = "CLEANUP_THROW",
+ [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1",
+ [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT",
[COMPARE_OP_INT] = "COMPARE_OP_INT",
[COMPARE_OP_STR] = "COMPARE_OP_STR",
- [FOR_ITER_LIST] = "FOR_ITER_LIST",
- [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE",
[STORE_SUBSCR] = "STORE_SUBSCR",
[DELETE_SUBSCR] = "DELETE_SUBSCR",
+ [FOR_ITER_LIST] = "FOR_ITER_LIST",
+ [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE",
[FOR_ITER_RANGE] = "FOR_ITER_RANGE",
[FOR_ITER_GEN] = "FOR_ITER_GEN",
[LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS",
[LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN",
- [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE",
- [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE",
[GET_ITER] = "GET_ITER",
[GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER",
- [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY",
+ [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE",
[LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS",
- [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT",
- [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT",
+ [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE",
+ [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY",
[LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR",
[RETURN_GENERATOR] = "RETURN_GENERATOR",
+ [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT",
+ [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT",
[LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT",
[LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT",
[LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES",
[LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST",
[LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST",
+ [RETURN_VALUE] = "RETURN_VALUE",
[LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST",
+ [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS",
[LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
- [RETURN_VALUE] = "RETURN_VALUE",
[LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
- [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS",
[STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE",
- [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
- [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT",
[POP_EXCEPT] = "POP_EXCEPT",
[STORE_NAME] = "STORE_NAME",
[DELETE_NAME] = "DELETE_NAME",
@@ -329,9 +348,9 @@ static const char *const _PyOpcode_OpName[263] = {
[IMPORT_NAME] = "IMPORT_NAME",
[IMPORT_FROM] = "IMPORT_FROM",
[JUMP_FORWARD] = "JUMP_FORWARD",
+ [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
+ [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT",
[STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST",
- [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST",
- [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT",
[POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE",
[POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE",
[LOAD_GLOBAL] = "LOAD_GLOBAL",
@@ -359,9 +378,9 @@ static const char *const _PyOpcode_OpName[263] = {
[STORE_DEREF] = "STORE_DEREF",
[DELETE_DEREF] = "DELETE_DEREF",
[JUMP_BACKWARD] = "JUMP_BACKWARD",
- [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT",
+ [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST",
[CALL_FUNCTION_EX] = "CALL_FUNCTION_EX",
- [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST",
+ [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT",
[EXTENDED_ARG] = "EXTENDED_ARG",
[LIST_APPEND] = "LIST_APPEND",
[SET_ADD] = "SET_ADD",
@@ -371,14 +390,14 @@ static const char *const _PyOpcode_OpName[263] = {
[YIELD_VALUE] = "YIELD_VALUE",
[RESUME] = "RESUME",
[MATCH_CLASS] = "MATCH_CLASS",
- [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE",
- [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE",
+ [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT",
+ [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST",
[FORMAT_VALUE] = "FORMAT_VALUE",
[BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP",
[BUILD_STRING] = "BUILD_STRING",
+ [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE",
+ [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE",
[SEND_GEN] = "SEND_GEN",
- [159] = "<159>",
- [160] = "<160>",
[161] = "<161>",
[LIST_EXTEND] = "LIST_EXTEND",
[SET_UPDATE] = "SET_UPDATE",
@@ -456,24 +475,24 @@ static const char *const _PyOpcode_OpName[263] = {
[235] = "<235>",
[236] = "<236>",
[237] = "<237>",
- [238] = "<238>",
- [239] = "<239>",
- [240] = "<240>",
- [241] = "<241>",
- [242] = "<242>",
- [243] = "<243>",
- [244] = "<244>",
- [245] = "<245>",
- [246] = "<246>",
- [247] = "<247>",
- [248] = "<248>",
- [249] = "<249>",
- [250] = "<250>",
- [251] = "<251>",
- [252] = "<252>",
- [253] = "<253>",
- [254] = "<254>",
- [DO_TRACING] = "DO_TRACING",
+ [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE",
+ [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE",
+ [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME",
+ [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL",
+ [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE",
+ [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE",
+ [INSTRUMENTED_CALL_FUNCTION_EX] = "INSTRUMENTED_CALL_FUNCTION_EX",
+ [INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD",
+ [INSTRUMENTED_JUMP_BACKWARD] = "INSTRUMENTED_JUMP_BACKWARD",
+ [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST",
+ [INSTRUMENTED_FOR_ITER] = "INSTRUMENTED_FOR_ITER",
+ [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE",
+ [INSTRUMENTED_POP_JUMP_IF_TRUE] = "INSTRUMENTED_POP_JUMP_IF_TRUE",
+ [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR",
+ [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND",
+ [INSTRUMENTED_INSTRUCTION] = "INSTRUMENTED_INSTRUCTION",
+ [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE",
+ [255] = "<255>",
[SETUP_FINALLY] = "SETUP_FINALLY",
[SETUP_CLEANUP] = "SETUP_CLEANUP",
[SETUP_WITH] = "SETUP_WITH",
@@ -485,8 +504,6 @@ static const char *const _PyOpcode_OpName[263] = {
#endif
#define EXTRA_CASES \
- case 159: \
- case 160: \
case 161: \
case 166: \
case 167: \
@@ -556,23 +573,7 @@ static const char *const _PyOpcode_OpName[263] = {
case 235: \
case 236: \
case 237: \
- case 238: \
- case 239: \
- case 240: \
- case 241: \
- case 242: \
- case 243: \
- case 244: \
- case 245: \
- case 246: \
- case 247: \
- case 248: \
- case 249: \
- case 250: \
- case 251: \
- case 252: \
- case 253: \
- case 254: \
+ case 255: \
;
#ifdef __cplusplus
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index b540862..6e5f228 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -133,16 +133,6 @@ extern void _PyThreadState_BindDetached(PyThreadState *);
extern void _PyThreadState_UnbindDetached(PyThreadState *);
-static inline void
-_PyThreadState_UpdateTracingState(PyThreadState *tstate)
-{
- bool use_tracing =
- (tstate->tracing == 0) &&
- (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL);
- tstate->cframe->use_tracing = (use_tracing ? 255 : 0);
-}
-
-
/* Other */
PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
diff --git a/Include/opcode.h b/Include/opcode.h
index 0ff84dc..aa8716e 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -13,10 +13,12 @@ extern "C" {
#define PUSH_NULL 2
#define INTERPRETER_EXIT 3
#define END_FOR 4
+#define END_SEND 5
#define NOP 9
#define UNARY_NEGATIVE 11
#define UNARY_NOT 12
#define UNARY_INVERT 15
+#define RESERVED 17
#define BINARY_SUBSCR 25
#define BINARY_SLICE 26
#define STORE_SLICE 27
@@ -114,6 +116,24 @@ extern "C" {
#define KW_NAMES 172
#define CALL_INTRINSIC_1 173
#define CALL_INTRINSIC_2 174
+#define MIN_INSTRUMENTED_OPCODE 238
+#define INSTRUMENTED_POP_JUMP_IF_NONE 238
+#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 239
+#define INSTRUMENTED_RESUME 240
+#define INSTRUMENTED_CALL 241
+#define INSTRUMENTED_RETURN_VALUE 242
+#define INSTRUMENTED_YIELD_VALUE 243
+#define INSTRUMENTED_CALL_FUNCTION_EX 244
+#define INSTRUMENTED_JUMP_FORWARD 245
+#define INSTRUMENTED_JUMP_BACKWARD 246
+#define INSTRUMENTED_RETURN_CONST 247
+#define INSTRUMENTED_FOR_ITER 248
+#define INSTRUMENTED_POP_JUMP_IF_FALSE 249
+#define INSTRUMENTED_POP_JUMP_IF_TRUE 250
+#define INSTRUMENTED_END_FOR 251
+#define INSTRUMENTED_END_SEND 252
+#define INSTRUMENTED_INSTRUCTION 253
+#define INSTRUMENTED_LINE 254
#define MIN_PSEUDO_OPCODE 256
#define SETUP_FINALLY 256
#define SETUP_CLEANUP 257
@@ -123,69 +143,68 @@ extern "C" {
#define JUMP_NO_INTERRUPT 261
#define LOAD_METHOD 262
#define MAX_PSEUDO_OPCODE 262
-#define BINARY_OP_ADD_FLOAT 5
-#define BINARY_OP_ADD_INT 6
-#define BINARY_OP_ADD_UNICODE 7
-#define BINARY_OP_INPLACE_ADD_UNICODE 8
-#define BINARY_OP_MULTIPLY_FLOAT 10
-#define BINARY_OP_MULTIPLY_INT 13
-#define BINARY_OP_SUBTRACT_FLOAT 14
-#define BINARY_OP_SUBTRACT_INT 16
-#define BINARY_SUBSCR_DICT 17
-#define BINARY_SUBSCR_GETITEM 18
-#define BINARY_SUBSCR_LIST_INT 19
-#define BINARY_SUBSCR_TUPLE_INT 20
-#define CALL_PY_EXACT_ARGS 21
-#define CALL_PY_WITH_DEFAULTS 22
-#define CALL_BOUND_METHOD_EXACT_ARGS 23
-#define CALL_BUILTIN_CLASS 24
-#define CALL_BUILTIN_FAST_WITH_KEYWORDS 28
-#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 29
-#define CALL_NO_KW_BUILTIN_FAST 34
-#define CALL_NO_KW_BUILTIN_O 38
-#define CALL_NO_KW_ISINSTANCE 39
-#define CALL_NO_KW_LEN 40
-#define CALL_NO_KW_LIST_APPEND 41
-#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 42
-#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 43
-#define CALL_NO_KW_METHOD_DESCRIPTOR_O 44
-#define CALL_NO_KW_STR_1 45
-#define CALL_NO_KW_TUPLE_1 46
-#define CALL_NO_KW_TYPE_1 47
-#define COMPARE_OP_FLOAT 48
-#define COMPARE_OP_INT 56
-#define COMPARE_OP_STR 57
-#define FOR_ITER_LIST 58
-#define FOR_ITER_TUPLE 59
-#define FOR_ITER_RANGE 62
-#define FOR_ITER_GEN 63
-#define LOAD_ATTR_CLASS 64
-#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 65
-#define LOAD_ATTR_INSTANCE_VALUE 66
-#define LOAD_ATTR_MODULE 67
-#define LOAD_ATTR_PROPERTY 70
-#define LOAD_ATTR_SLOT 72
-#define LOAD_ATTR_WITH_HINT 73
-#define LOAD_ATTR_METHOD_LAZY_DICT 76
-#define LOAD_ATTR_METHOD_NO_DICT 77
-#define LOAD_ATTR_METHOD_WITH_VALUES 78
-#define LOAD_CONST__LOAD_FAST 79
-#define LOAD_FAST__LOAD_CONST 80
-#define LOAD_FAST__LOAD_FAST 81
-#define LOAD_GLOBAL_BUILTIN 82
-#define LOAD_GLOBAL_MODULE 84
-#define STORE_ATTR_INSTANCE_VALUE 86
-#define STORE_ATTR_SLOT 87
-#define STORE_ATTR_WITH_HINT 88
-#define STORE_FAST__LOAD_FAST 111
-#define STORE_FAST__STORE_FAST 112
-#define STORE_SUBSCR_DICT 113
-#define STORE_SUBSCR_LIST_INT 141
-#define UNPACK_SEQUENCE_LIST 143
-#define UNPACK_SEQUENCE_TUPLE 153
-#define UNPACK_SEQUENCE_TWO_TUPLE 154
-#define SEND_GEN 158
-#define DO_TRACING 255
+#define BINARY_OP_ADD_FLOAT 6
+#define BINARY_OP_ADD_INT 7
+#define BINARY_OP_ADD_UNICODE 8
+#define BINARY_OP_INPLACE_ADD_UNICODE 10
+#define BINARY_OP_MULTIPLY_FLOAT 13
+#define BINARY_OP_MULTIPLY_INT 14
+#define BINARY_OP_SUBTRACT_FLOAT 16
+#define BINARY_OP_SUBTRACT_INT 18
+#define BINARY_SUBSCR_DICT 19
+#define BINARY_SUBSCR_GETITEM 20
+#define BINARY_SUBSCR_LIST_INT 21
+#define BINARY_SUBSCR_TUPLE_INT 22
+#define CALL_PY_EXACT_ARGS 23
+#define CALL_PY_WITH_DEFAULTS 24
+#define CALL_BOUND_METHOD_EXACT_ARGS 28
+#define CALL_BUILTIN_CLASS 29
+#define CALL_BUILTIN_FAST_WITH_KEYWORDS 34
+#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 38
+#define CALL_NO_KW_BUILTIN_FAST 39
+#define CALL_NO_KW_BUILTIN_O 40
+#define CALL_NO_KW_ISINSTANCE 41
+#define CALL_NO_KW_LEN 42
+#define CALL_NO_KW_LIST_APPEND 43
+#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST 44
+#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 45
+#define CALL_NO_KW_METHOD_DESCRIPTOR_O 46
+#define CALL_NO_KW_STR_1 47
+#define CALL_NO_KW_TUPLE_1 48
+#define CALL_NO_KW_TYPE_1 56
+#define COMPARE_OP_FLOAT 57
+#define COMPARE_OP_INT 58
+#define COMPARE_OP_STR 59
+#define FOR_ITER_LIST 62
+#define FOR_ITER_TUPLE 63
+#define FOR_ITER_RANGE 64
+#define FOR_ITER_GEN 65
+#define LOAD_ATTR_CLASS 66
+#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 67
+#define LOAD_ATTR_INSTANCE_VALUE 70
+#define LOAD_ATTR_MODULE 72
+#define LOAD_ATTR_PROPERTY 73
+#define LOAD_ATTR_SLOT 76
+#define LOAD_ATTR_WITH_HINT 77
+#define LOAD_ATTR_METHOD_LAZY_DICT 78
+#define LOAD_ATTR_METHOD_NO_DICT 79
+#define LOAD_ATTR_METHOD_WITH_VALUES 80
+#define LOAD_CONST__LOAD_FAST 81
+#define LOAD_FAST__LOAD_CONST 82
+#define LOAD_FAST__LOAD_FAST 84
+#define LOAD_GLOBAL_BUILTIN 86
+#define LOAD_GLOBAL_MODULE 87
+#define STORE_ATTR_INSTANCE_VALUE 88
+#define STORE_ATTR_SLOT 111
+#define STORE_ATTR_WITH_HINT 112
+#define STORE_FAST__LOAD_FAST 113
+#define STORE_FAST__STORE_FAST 141
+#define STORE_SUBSCR_DICT 143
+#define STORE_SUBSCR_LIST_INT 153
+#define UNPACK_SEQUENCE_LIST 154
+#define UNPACK_SEQUENCE_TUPLE 158
+#define UNPACK_SEQUENCE_TWO_TUPLE 159
+#define SEND_GEN 160
#define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\
|| ((op) == JUMP) \