+#include "Python.h"
+#include "pycore_ceval.h"
+#include "pycore_object.h"
+#include "pycore_sysmodule.h"
+
+typedef struct _PyLegacyEventHandler {
+ PyObject_HEAD
+ vectorcallfunc vectorcall;
+ int event;
+} _PyLegacyEventHandler;
+
+/* The Py_tracefunc function expects the following arguments:
+ * obj: the trace object (PyObject *)
+ * frame: the current frame (PyFrameObject *)
+ * kind: the kind of event, see PyTrace_XXX #defines (int)
+ * arg: The arg (a PyObject *)
+ */
+
+static PyObject *
+call_profile_func(_PyLegacyEventHandler *self, PyObject *arg)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate->c_profilefunc == NULL) {
+ Py_RETURN_NONE;
+ }
+ PyFrameObject *frame = PyEval_GetFrame();
+ if (frame == NULL) {
+ PyErr_SetString(PyExc_SystemError,
+ "Missing frame when calling profile function.");
+ return NULL;
+ }
+ Py_INCREF(frame);
+ int err = tstate->c_profilefunc(tstate->c_profileobj, frame, self->event, arg);
+ Py_DECREF(frame);
+ if (err) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+sys_profile_func2(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 2);
+ return call_profile_func(self, Py_None);
+}
+
+static PyObject *
+sys_profile_func3(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ return call_profile_func(self, args[2]);
+}
+
+static PyObject *
+sys_profile_call_or_return(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 4);
+ PyObject *callable = args[2];
+ if (PyCFunction_Check(callable)) {
+ return call_profile_func(self, callable);
+ }
+ if (Py_TYPE(callable) == &PyMethodDescr_Type) {
+ PyObject *self_arg = args[3];
+ /* For backwards compatibility need to
+ * convert to builtin method */
+
+ /* If no arg, skip */
+ if (self_arg == &_PyInstrumentation_MISSING) {
+ Py_RETURN_NONE;
+ }
+ PyObject *meth = Py_TYPE(callable)->tp_descr_get(
+ callable, self_arg, (PyObject*)Py_TYPE(self_arg));
+ if (meth == NULL) {
+ return NULL;
+ }
+ PyObject *res = call_profile_func(self, meth);
+ Py_DECREF(meth);
+ return res;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+call_trace_func(_PyLegacyEventHandler *self, PyObject *arg)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate->c_tracefunc == NULL) {
+ Py_RETURN_NONE;
+ }
+ PyFrameObject *frame = PyEval_GetFrame();
+ if (frame == NULL) {
+ PyErr_SetString(PyExc_SystemError,
+ "Missing frame when calling trace function.");
+ return NULL;
+ }
+ Py_INCREF(frame);
+ int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg);
+ Py_DECREF(frame);
+ if (err) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+sys_trace_exception_func(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ PyObject *exc = args[2];
+ assert(PyExceptionInstance_Check(exc));
+ PyObject *type = (PyObject *)Py_TYPE(exc);
+ PyObject *tb = PyException_GetTraceback(exc);
+ if (tb == NULL) {
+ tb = Py_NewRef(Py_None);
+ }
+ PyObject *tuple = PyTuple_Pack(3, type, exc, tb);
+ Py_DECREF(tb);
+ if (tuple == NULL) {
+ return NULL;
+ }
+ PyObject *res = call_trace_func(self, tuple);
+ Py_DECREF(tuple);
+ return res;
+}
+
+static PyObject *
+sys_trace_func2(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 2);
+ return call_trace_func(self, Py_None);
+}
+
+static PyObject *
+sys_trace_return(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(!PyErr_Occurred());
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ assert(PyCode_Check(args[0]));
+ PyObject *val = args[2];
+ PyObject *res = call_trace_func(self, val);
+ return res;
+}
+
+static PyObject *
+sys_trace_yield(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ return call_trace_func(self, args[2]);
+}
+
+static PyObject *
+sys_trace_instruction_func(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ assert(PyVectorcall_NARGS(nargsf) == 2);
+ PyFrameObject *frame = PyEval_GetFrame();
+ if (frame == NULL) {
+ PyErr_SetString(PyExc_SystemError,
+ "Missing frame when calling trace function.");
+ return NULL;
+ }
+ if (!frame->f_trace_opcodes) {
+ Py_RETURN_NONE;
+ }
+ Py_INCREF(frame);
+ PyThreadState *tstate = _PyThreadState_GET();
+ int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
+ frame->f_lineno = 0;
+ Py_DECREF(frame);
+ if (err) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+trace_line(
+ PyThreadState *tstate, _PyLegacyEventHandler *self,
+ PyFrameObject *frame, int line
+) {
+ if (!frame->f_trace_lines) {
+ Py_RETURN_NONE;
+ }
+ if (line < 0) {
+ Py_RETURN_NONE;
+ }
+ frame ->f_last_traced_line = line;
+ Py_INCREF(frame);
+ frame->f_lineno = line;
+ int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);
+ frame->f_lineno = 0;
+ Py_DECREF(frame);
+ if (err) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+sys_trace_line_func(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate->c_tracefunc == NULL) {
+ Py_RETURN_NONE;
+ }
+ assert(PyVectorcall_NARGS(nargsf) == 2);
+ int line = _PyLong_AsInt(args[1]);
+ assert(line >= 0);
+ PyFrameObject *frame = PyEval_GetFrame();
+ if (frame == NULL) {
+ PyErr_SetString(PyExc_SystemError,
+ "Missing frame when calling trace function.");
+ return NULL;
+ }
+ assert(args[0] == (PyObject *)frame->f_frame->f_code);
+ if (frame ->f_last_traced_line == line) {
+ /* Already traced this line */
+ Py_RETURN_NONE;
+ }
+ return trace_line(tstate, self, frame, line);
+}
+
+
+static PyObject *
+sys_trace_jump_func(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate->c_tracefunc == NULL) {
+ Py_RETURN_NONE;
+ }
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ int from = _PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT);
+ assert(from >= 0);
+ int to = _PyLong_AsInt(args[2])/sizeof(_Py_CODEUNIT);
+ assert(to >= 0);
+ PyFrameObject *frame = PyEval_GetFrame();
+ if (frame == NULL) {
+ PyErr_SetString(PyExc_SystemError,
+ "Missing frame when calling trace function.");
+ return NULL;
+ }
+ if (!frame->f_trace_lines) {
+ Py_RETURN_NONE;
+ }
+ PyCodeObject *code = (PyCodeObject *)args[0];
+ assert(PyCode_Check(code));
+ assert(code == frame->f_frame->f_code);
+ /* We can call _Py_Instrumentation_GetLine because we always set
+ * line events for tracing */
+ int to_line = _Py_Instrumentation_GetLine(code, to);
+ /* Backward jump: Always generate event
+ * Forward jump: Only generate event if jumping to different line. */
+ if (to > from && frame->f_last_traced_line == to_line) {
+ /* Already traced this line */
+ Py_RETURN_NONE;
+ }
+ return trace_line(tstate, self, frame, to_line);
+}
+
+/* We don't care about the exception here,
+ * we just treat it as a possible new line
+ */
+static PyObject *
+sys_trace_exception_handled(
+ _PyLegacyEventHandler *self, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames
+) {
+ assert(kwnames == NULL);
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate->c_tracefunc == NULL) {
+ Py_RETURN_NONE;
+ }
+ assert(PyVectorcall_NARGS(nargsf) == 3);
+ PyFrameObject *frame = PyEval_GetFrame();
+ PyCodeObject *code = (PyCodeObject *)args[0];
+ assert(PyCode_Check(code));
+ assert(code == frame->f_frame->f_code);
+ assert(PyLong_Check(args[1]));
+ int offset = _PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT);
+ /* We can call _Py_Instrumentation_GetLine because we always set
+ * line events for tracing */
+ int line = _Py_Instrumentation_GetLine(code, offset);
+ if (frame->f_last_traced_line == line) {
+ /* Already traced this line */
+ Py_RETURN_NONE;
+ }
+ return trace_line(tstate, self, frame, line);
+}
+
+
+PyTypeObject _PyLegacyEventHandler_Type = {
+ _PyVarObject_IMMORTAL_INIT(&PyType_Type, 0),
+ "sys.legacy_event_handler",
+ sizeof(_PyLegacyEventHandler),
+ .tp_dealloc = (destructor)PyObject_Free,
+ .tp_vectorcall_offset = offsetof(_PyLegacyEventHandler, vectorcall),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_DISALLOW_INSTANTIATION,
+ .tp_call = PyVectorcall_Call,
+};
+
+static int
+set_callbacks(int tool, vectorcallfunc vectorcall, int legacy_event, int event1, int event2)
+{
+ _PyLegacyEventHandler *callback =
+ PyObject_NEW(_PyLegacyEventHandler, &_PyLegacyEventHandler_Type);
+ if (callback == NULL) {
+ return -1;
+ }
+ callback->vectorcall = vectorcall;
+ callback->event = legacy_event;
+ Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event1, (PyObject *)callback));
+ if (event2 >= 0) {
+ Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event2, (PyObject *)callback));
+ }
+ Py_DECREF(callback);
+ return 0;
+}
+
+#ifndef NDEBUG
+/* Ensure that tstate is valid: sanity check for PyEval_AcquireThread() and
+ PyEval_RestoreThread(). Detect if tstate memory was freed. It can happen
+ when a thread continues to run after Python finalization, especially
+ daemon threads. */
+static int
+is_tstate_valid(PyThreadState *tstate)
+{
+ assert(!_PyMem_IsPtrFreed(tstate));
+ assert(!_PyMem_IsPtrFreed(tstate->interp));
+ return 1;
+}
+#endif
+
+int
+_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
+{
+ assert(is_tstate_valid(tstate));
+ /* The caller must hold the GIL */
+ assert(PyGILState_Check());
+
+ /* Call _PySys_Audit() in the context of the current thread state,
+ even if tstate is not the current thread state. */
+ PyThreadState *current_tstate = _PyThreadState_GET();
+ if (_PySys_Audit(current_tstate, "sys.setprofile", NULL) < 0) {
+ return -1;
+ }
+ /* Setup PEP 669 monitoring callbacks and events. */
+ if (!tstate->interp->sys_profile_initialized) {
+ tstate->interp->sys_profile_initialized = true;
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_func2, PyTrace_CALL,
+ PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_func3, PyTrace_RETURN,
+ PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_func2, PyTrace_RETURN,
+ PY_MONITORING_EVENT_PY_UNWIND, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_CALL,
+ PY_MONITORING_EVENT_CALL, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_RETURN,
+ PY_MONITORING_EVENT_C_RETURN, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,
+ (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_EXCEPTION,
+ PY_MONITORING_EVENT_C_RAISE, -1)) {
+ return -1;
+ }
+ }
+
+ int delta = (func != NULL) - (tstate->c_profilefunc != NULL);
+ tstate->c_profilefunc = func;
+ PyObject *old_profileobj = tstate->c_profileobj;
+ tstate->c_profileobj = Py_XNewRef(arg);
+ Py_XDECREF(old_profileobj);
+ tstate->interp->sys_profiling_threads += delta;
+ assert(tstate->interp->sys_profiling_threads >= 0);
+
+ uint32_t events = 0;
+ if (tstate->interp->sys_profiling_threads) {
+ events =
+ (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |
+ (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |
+ (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND);
+ }
+ return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events);
+}
+
+int
+_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
+{
+ assert(is_tstate_valid(tstate));
+ /* The caller must hold the GIL */
+ assert(PyGILState_Check());
+
+ /* Call _PySys_Audit() in the context of the current thread state,
+ even if tstate is not the current thread state. */
+ PyThreadState *current_tstate = _PyThreadState_GET();
+ if (_PySys_Audit(current_tstate, "sys.settrace", NULL) < 0) {
+ return -1;
+ }
+
+ assert(tstate->interp->sys_tracing_threads >= 0);
+ /* Setup PEP 669 monitoring callbacks and events. */
+ if (!tstate->interp->sys_trace_initialized) {
+ tstate->interp->sys_trace_initialized = true;
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_func2, PyTrace_CALL,
+ PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_func2, PyTrace_CALL,
+ PY_MONITORING_EVENT_PY_THROW, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_return, PyTrace_RETURN,
+ PY_MONITORING_EVENT_PY_RETURN, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_yield, PyTrace_RETURN,
+ PY_MONITORING_EVENT_PY_YIELD, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_exception_func, PyTrace_EXCEPTION,
+ PY_MONITORING_EVENT_RAISE, PY_MONITORING_EVENT_STOP_ITERATION)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_line_func, PyTrace_LINE,
+ PY_MONITORING_EVENT_LINE, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_func2, PyTrace_RETURN,
+ PY_MONITORING_EVENT_PY_UNWIND, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_jump_func, PyTrace_LINE,
+ PY_MONITORING_EVENT_JUMP, PY_MONITORING_EVENT_BRANCH)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_instruction_func, PyTrace_OPCODE,
+ PY_MONITORING_EVENT_INSTRUCTION, -1)) {
+ return -1;
+ }
+ if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,
+ (vectorcallfunc)sys_trace_exception_handled, PyTrace_LINE,
+ PY_MONITORING_EVENT_EXCEPTION_HANDLED, -1)) {
+ return -1;
+ }
+ }
+
+ int delta = (func != NULL) - (tstate->c_tracefunc != NULL);
+ tstate->c_tracefunc = func;
+ PyObject *old_traceobj = tstate->c_traceobj;
+ tstate->c_traceobj = Py_XNewRef(arg);
+ Py_XDECREF(old_traceobj);
+ tstate->interp->sys_tracing_threads += delta;
+ assert(tstate->interp->sys_tracing_threads >= 0);
+
+ uint32_t events = 0;
+ if (tstate->interp->sys_tracing_threads) {
+ events =
+ (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |
+ (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |
+ (1 << PY_MONITORING_EVENT_RAISE) | (1 << PY_MONITORING_EVENT_LINE) |
+ (1 << PY_MONITORING_EVENT_JUMP) | (1 << PY_MONITORING_EVENT_BRANCH) |
+ (1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) |
+ (1 << PY_MONITORING_EVENT_STOP_ITERATION) |
+ (1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED);
+ if (tstate->interp->f_opcode_trace_set) {
+ events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);
+ }
+ }
+ return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events);
+}
diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py
index 33a4b4a76a1253..5aa31803397ce4 100755
--- a/Python/makeopcodetargets.py
+++ b/Python/makeopcodetargets.py
@@ -32,7 +32,6 @@ def write_contents(f):
"""
opcode = find_module('opcode')
targets = ['_unknown_opcode'] * 256
- targets[255] = "TARGET_DO_TRACING"
for opname, op in opcode.opmap.items():
if not opcode.is_pseudo(op):
targets[op] = "TARGET_%s" % opname
diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h
index f57b76aeb31050..4681ed03aff582 100644
--- a/Python/opcode_metadata.h
+++ b/Python/opcode_metadata.h
@@ -13,6 +13,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 0;
case RESUME:
return 0;
+ case INSTRUMENTED_RESUME:
+ return 0;
case LOAD_CLOSURE:
return 0;
case LOAD_FAST_CHECK:
@@ -39,6 +41,12 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 0;
case END_FOR:
return 1+1;
+ case INSTRUMENTED_END_FOR:
+ return 2;
+ case END_SEND:
+ return 2;
+ case INSTRUMENTED_END_SEND:
+ return 2;
case UNARY_NEGATIVE:
return 1;
case UNARY_NOT:
@@ -97,8 +105,12 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1;
case RETURN_VALUE:
return 1;
+ case INSTRUMENTED_RETURN_VALUE:
+ return 1;
case RETURN_CONST:
return 0;
+ case INSTRUMENTED_RETURN_CONST:
+ return 0;
case GET_AITER:
return 1;
case GET_ANEXT:
@@ -109,6 +121,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 2;
case SEND_GEN:
return 2;
+ case INSTRUMENTED_YIELD_VALUE:
+ return 1;
case YIELD_VALUE:
return 1;
case POP_EXCEPT:
@@ -263,6 +277,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1;
case FOR_ITER:
return 1;
+ case INSTRUMENTED_FOR_ITER:
+ return 0;
case FOR_ITER_LIST:
return 1;
case FOR_ITER_TUPLE:
@@ -287,6 +303,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1;
case KW_NAMES:
return 0;
+ case INSTRUMENTED_CALL:
+ return 0;
case CALL:
return oparg + 2;
case CALL_BOUND_METHOD_EXACT_ARGS:
@@ -323,6 +341,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return oparg + 2;
case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
return oparg + 2;
+ case INSTRUMENTED_CALL_FUNCTION_EX:
+ return 0;
case CALL_FUNCTION_EX:
return ((oparg & 1) ? 1 : 0) + 3;
case MAKE_FUNCTION:
@@ -339,10 +359,28 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 2;
case SWAP:
return (oparg-2) + 2;
+ case INSTRUMENTED_LINE:
+ return 0;
+ case INSTRUMENTED_INSTRUCTION:
+ return 0;
+ case INSTRUMENTED_JUMP_FORWARD:
+ return 0;
+ case INSTRUMENTED_JUMP_BACKWARD:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_TRUE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_FALSE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_NONE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:
+ return 0;
case EXTENDED_ARG:
return 0;
case CACHE:
return 0;
+ case RESERVED:
+ return 0;
default:
return -1;
}
@@ -359,6 +397,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0;
case RESUME:
return 0;
+ case INSTRUMENTED_RESUME:
+ return 0;
case LOAD_CLOSURE:
return 1;
case LOAD_FAST_CHECK:
@@ -385,6 +425,12 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 1;
case END_FOR:
return 0+0;
+ case INSTRUMENTED_END_FOR:
+ return 0;
+ case END_SEND:
+ return 1;
+ case INSTRUMENTED_END_SEND:
+ return 1;
case UNARY_NEGATIVE:
return 1;
case UNARY_NOT:
@@ -443,8 +489,12 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0;
case RETURN_VALUE:
return 0;
+ case INSTRUMENTED_RETURN_VALUE:
+ return 0;
case RETURN_CONST:
return 0;
+ case INSTRUMENTED_RETURN_CONST:
+ return 0;
case GET_AITER:
return 1;
case GET_ANEXT:
@@ -455,6 +505,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 2;
case SEND_GEN:
return 1;
+ case INSTRUMENTED_YIELD_VALUE:
+ return 1;
case YIELD_VALUE:
return 1;
case POP_EXCEPT:
@@ -609,6 +661,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 1;
case FOR_ITER:
return 2;
+ case INSTRUMENTED_FOR_ITER:
+ return 0;
case FOR_ITER_LIST:
return 2;
case FOR_ITER_TUPLE:
@@ -633,6 +687,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return ((oparg & 1) ? 1 : 0) + 1;
case KW_NAMES:
return 0;
+ case INSTRUMENTED_CALL:
+ return 0;
case CALL:
return 1;
case CALL_BOUND_METHOD_EXACT_ARGS:
@@ -669,6 +725,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 1;
case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
return 1;
+ case INSTRUMENTED_CALL_FUNCTION_EX:
+ return 0;
case CALL_FUNCTION_EX:
return 1;
case MAKE_FUNCTION:
@@ -685,10 +743,28 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 1;
case SWAP:
return (oparg-2) + 2;
+ case INSTRUMENTED_LINE:
+ return 0;
+ case INSTRUMENTED_INSTRUCTION:
+ return 0;
+ case INSTRUMENTED_JUMP_FORWARD:
+ return 0;
+ case INSTRUMENTED_JUMP_BACKWARD:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_TRUE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_FALSE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_NONE:
+ return 0;
+ case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:
+ return 0;
case EXTENDED_ARG:
return 0;
case CACHE:
return 0;
+ case RESERVED:
+ return 0;
default:
return -1;
}
@@ -707,6 +783,7 @@ extern const struct opcode_metadata _PyOpcode_opcode_metadata[256];
const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[NOP] = { true, INSTR_FMT_IX },
[RESUME] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB },
[LOAD_CLOSURE] = { true, INSTR_FMT_IB },
[LOAD_FAST_CHECK] = { true, INSTR_FMT_IB },
[LOAD_FAST] = { true, INSTR_FMT_IB },
@@ -720,6 +797,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[POP_TOP] = { true, INSTR_FMT_IX },
[PUSH_NULL] = { true, INSTR_FMT_IX },
[END_FOR] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX },
+ [END_SEND] = { true, INSTR_FMT_IX },
+ [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX },
[UNARY_NEGATIVE] = { true, INSTR_FMT_IX },
[UNARY_NOT] = { true, INSTR_FMT_IX },
[UNARY_INVERT] = { true, INSTR_FMT_IX },
@@ -749,12 +829,15 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[RAISE_VARARGS] = { true, INSTR_FMT_IB },
[INTERPRETER_EXIT] = { true, INSTR_FMT_IX },
[RETURN_VALUE] = { true, INSTR_FMT_IX },
+ [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX },
[RETURN_CONST] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB },
[GET_AITER] = { true, INSTR_FMT_IX },
[GET_ANEXT] = { true, INSTR_FMT_IX },
[GET_AWAITABLE] = { true, INSTR_FMT_IB },
[SEND] = { true, INSTR_FMT_IBC },
[SEND_GEN] = { true, INSTR_FMT_IBC },
+ [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IX },
[YIELD_VALUE] = { true, INSTR_FMT_IX },
[POP_EXCEPT] = { true, INSTR_FMT_IX },
[RERAISE] = { true, INSTR_FMT_IB },
@@ -832,6 +915,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[GET_ITER] = { true, INSTR_FMT_IX },
[GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX },
[FOR_ITER] = { true, INSTR_FMT_IBC },
+ [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB },
[FOR_ITER_LIST] = { true, INSTR_FMT_IBC },
[FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC },
[FOR_ITER_RANGE] = { true, INSTR_FMT_IBC },
@@ -844,6 +928,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000 },
[LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000 },
[KW_NAMES] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB },
[CALL] = { true, INSTR_FMT_IBC00 },
[CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },
[CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },
@@ -862,6 +947,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00 },
[CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00 },
[CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00 },
+ [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX },
[CALL_FUNCTION_EX] = { true, INSTR_FMT_IB },
[MAKE_FUNCTION] = { true, INSTR_FMT_IB },
[RETURN_GENERATOR] = { true, INSTR_FMT_IX },
@@ -870,7 +956,16 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
[COPY] = { true, INSTR_FMT_IB },
[BINARY_OP] = { true, INSTR_FMT_IBC },
[SWAP] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_LINE] = { true, INSTR_FMT_IX },
+ [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX },
+ [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB },
+ [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB },
[EXTENDED_ARG] = { true, INSTR_FMT_IB },
[CACHE] = { true, INSTR_FMT_IX },
+ [RESERVED] = { true, INSTR_FMT_IX },
};
#endif
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index c502471bcd17b6..9d6616666f7ac1 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -4,17 +4,19 @@ static void *opcode_targets[256] = {
&&TARGET_PUSH_NULL,
&&TARGET_INTERPRETER_EXIT,
&&TARGET_END_FOR,
+ &&TARGET_END_SEND,
&&TARGET_BINARY_OP_ADD_FLOAT,
&&TARGET_BINARY_OP_ADD_INT,
&&TARGET_BINARY_OP_ADD_UNICODE,
- &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
&&TARGET_NOP,
- &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
+ &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
&&TARGET_UNARY_NEGATIVE,
&&TARGET_UNARY_NOT,
+ &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
&&TARGET_BINARY_OP_MULTIPLY_INT,
- &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
&&TARGET_UNARY_INVERT,
+ &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
+ &&TARGET_RESERVED,
&&TARGET_BINARY_OP_SUBTRACT_INT,
&&TARGET_BINARY_SUBSCR_DICT,
&&TARGET_BINARY_SUBSCR_GETITEM,
@@ -22,21 +24,21 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
&&TARGET_CALL_PY_EXACT_ARGS,
&&TARGET_CALL_PY_WITH_DEFAULTS,
- &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
- &&TARGET_CALL_BUILTIN_CLASS,
&&TARGET_BINARY_SUBSCR,
&&TARGET_BINARY_SLICE,
&&TARGET_STORE_SLICE,
- &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
- &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
+ &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
+ &&TARGET_CALL_BUILTIN_CLASS,
&&TARGET_GET_LEN,
&&TARGET_MATCH_MAPPING,
&&TARGET_MATCH_SEQUENCE,
&&TARGET_MATCH_KEYS,
- &&TARGET_CALL_NO_KW_BUILTIN_FAST,
+ &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
&&TARGET_PUSH_EXC_INFO,
&&TARGET_CHECK_EXC_MATCH,
&&TARGET_CHECK_EG_MATCH,
+ &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
+ &&TARGET_CALL_NO_KW_BUILTIN_FAST,
&&TARGET_CALL_NO_KW_BUILTIN_O,
&&TARGET_CALL_NO_KW_ISINSTANCE,
&&TARGET_CALL_NO_KW_LEN,
@@ -46,8 +48,6 @@ static void *opcode_targets[256] = {
&&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
&&TARGET_CALL_NO_KW_STR_1,
&&TARGET_CALL_NO_KW_TUPLE_1,
- &&TARGET_CALL_NO_KW_TYPE_1,
- &&TARGET_COMPARE_OP_FLOAT,
&&TARGET_WITH_EXCEPT_START,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
@@ -55,39 +55,39 @@ static void *opcode_targets[256] = {
&&TARGET_BEFORE_WITH,
&&TARGET_END_ASYNC_FOR,
&&TARGET_CLEANUP_THROW,
+ &&TARGET_CALL_NO_KW_TYPE_1,
+ &&TARGET_COMPARE_OP_FLOAT,
&&TARGET_COMPARE_OP_INT,
&&TARGET_COMPARE_OP_STR,
- &&TARGET_FOR_ITER_LIST,
- &&TARGET_FOR_ITER_TUPLE,
&&TARGET_STORE_SUBSCR,
&&TARGET_DELETE_SUBSCR,
+ &&TARGET_FOR_ITER_LIST,
+ &&TARGET_FOR_ITER_TUPLE,
&&TARGET_FOR_ITER_RANGE,
&&TARGET_FOR_ITER_GEN,
&&TARGET_LOAD_ATTR_CLASS,
&&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
- &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
- &&TARGET_LOAD_ATTR_MODULE,
&&TARGET_GET_ITER,
&&TARGET_GET_YIELD_FROM_ITER,
- &&TARGET_LOAD_ATTR_PROPERTY,
+ &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
&&TARGET_LOAD_BUILD_CLASS,
- &&TARGET_LOAD_ATTR_SLOT,
- &&TARGET_LOAD_ATTR_WITH_HINT,
+ &&TARGET_LOAD_ATTR_MODULE,
+ &&TARGET_LOAD_ATTR_PROPERTY,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_RETURN_GENERATOR,
+ &&TARGET_LOAD_ATTR_SLOT,
+ &&TARGET_LOAD_ATTR_WITH_HINT,
&&TARGET_LOAD_ATTR_METHOD_LAZY_DICT,
&&TARGET_LOAD_ATTR_METHOD_NO_DICT,
&&TARGET_LOAD_ATTR_METHOD_WITH_VALUES,
&&TARGET_LOAD_CONST__LOAD_FAST,
&&TARGET_LOAD_FAST__LOAD_CONST,
+ &&TARGET_RETURN_VALUE,
&&TARGET_LOAD_FAST__LOAD_FAST,
+ &&TARGET_SETUP_ANNOTATIONS,
&&TARGET_LOAD_GLOBAL_BUILTIN,
- &&TARGET_RETURN_VALUE,
&&TARGET_LOAD_GLOBAL_MODULE,
- &&TARGET_SETUP_ANNOTATIONS,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
- &&TARGET_STORE_ATTR_SLOT,
- &&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_POP_EXCEPT,
&&TARGET_STORE_NAME,
&&TARGET_DELETE_NAME,
@@ -110,9 +110,9 @@ static void *opcode_targets[256] = {
&&TARGET_IMPORT_NAME,
&&TARGET_IMPORT_FROM,
&&TARGET_JUMP_FORWARD,
+ &&TARGET_STORE_ATTR_SLOT,
+ &&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_STORE_FAST__LOAD_FAST,
- &&TARGET_STORE_FAST__STORE_FAST,
- &&TARGET_STORE_SUBSCR_DICT,
&&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL,
@@ -140,9 +140,9 @@ static void *opcode_targets[256] = {
&&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF,
&&TARGET_JUMP_BACKWARD,
- &&TARGET_STORE_SUBSCR_LIST_INT,
+ &&TARGET_STORE_FAST__STORE_FAST,
&&TARGET_CALL_FUNCTION_EX,
- &&TARGET_UNPACK_SEQUENCE_LIST,
+ &&TARGET_STORE_SUBSCR_DICT,
&&TARGET_EXTENDED_ARG,
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
@@ -152,15 +152,15 @@ static void *opcode_targets[256] = {
&&TARGET_YIELD_VALUE,
&&TARGET_RESUME,
&&TARGET_MATCH_CLASS,
- &&TARGET_UNPACK_SEQUENCE_TUPLE,
- &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
+ &&TARGET_STORE_SUBSCR_LIST_INT,
+ &&TARGET_UNPACK_SEQUENCE_LIST,
&&TARGET_FORMAT_VALUE,
&&TARGET_BUILD_CONST_KEY_MAP,
&&TARGET_BUILD_STRING,
+ &&TARGET_UNPACK_SEQUENCE_TUPLE,
+ &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
&&TARGET_SEND_GEN,
&&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_LIST_EXTEND,
&&TARGET_SET_UPDATE,
&&TARGET_DICT_MERGE,
@@ -237,22 +237,22 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&TARGET_DO_TRACING
+ &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE,
+ &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE,
+ &&TARGET_INSTRUMENTED_RESUME,
+ &&TARGET_INSTRUMENTED_CALL,
+ &&TARGET_INSTRUMENTED_RETURN_VALUE,
+ &&TARGET_INSTRUMENTED_YIELD_VALUE,
+ &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
+ &&TARGET_INSTRUMENTED_JUMP_FORWARD,
+ &&TARGET_INSTRUMENTED_JUMP_BACKWARD,
+ &&TARGET_INSTRUMENTED_RETURN_CONST,
+ &&TARGET_INSTRUMENTED_FOR_ITER,
+ &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE,
+ &&TARGET_INSTRUMENTED_POP_JUMP_IF_TRUE,
+ &&TARGET_INSTRUMENTED_END_FOR,
+ &&TARGET_INSTRUMENTED_END_SEND,
+ &&TARGET_INSTRUMENTED_INSTRUCTION,
+ &&TARGET_INSTRUMENTED_LINE,
+ &&_unknown_opcode
};
diff --git a/Python/pystate.c b/Python/pystate.c
index 1e59a8c5f89717..3818434c485194 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -637,7 +637,6 @@ free_interpreter(PyInterpreterState *interp)
main interpreter. We fix those fields here, in addition
to the other dynamically initialized fields.
*/
-
static void
init_interpreter(PyInterpreterState *interp,
_PyRuntimeState *runtime, int64_t id,
@@ -662,12 +661,22 @@ init_interpreter(PyInterpreterState *interp,
_PyGC_InitState(&interp->gc);
PyConfig_InitPythonConfig(&interp->config);
_PyType_InitCache(interp);
+ for(int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {
+ interp->monitors.tools[i] = 0;
+ }
+ for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {
+ for(int e = 0; e < PY_MONITORING_EVENTS; e++) {
+ interp->monitoring_callables[t][e] = NULL;
+ }
+ }
+ interp->sys_profile_initialized = false;
+ interp->sys_trace_initialized = false;
if (interp != &runtime->_main_interpreter) {
/* Fix the self-referential, statically initialized fields. */
interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);
}
-
+ interp->f_opcode_trace_set = false;
interp->_initialized = 1;
}
@@ -800,6 +809,20 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
Py_CLEAR(interp->audit_hooks);
+ for(int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {
+ interp->monitors.tools[i] = 0;
+ }
+ for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {
+ for(int e = 0; e < PY_MONITORING_EVENTS; e++) {
+ Py_CLEAR(interp->monitoring_callables[t][e]);
+ }
+ }
+ interp->sys_profile_initialized = false;
+ interp->sys_trace_initialized = false;
+ for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {
+ Py_CLEAR(interp->monitoring_tool_names[t]);
+ }
+
PyConfig_Clear(&interp->config);
Py_CLEAR(interp->codec_search_path);
Py_CLEAR(interp->codec_search_cache);
@@ -857,7 +880,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
interp->code_watchers[i] = NULL;
}
interp->active_code_watchers = 0;
-
+ interp->f_opcode_trace_set = false;
// XXX Once we have one allocator per interpreter (i.e.
// per-interpreter GC) we must ensure that all of the interpreter's
// objects have been cleaned up at the point.
@@ -1249,6 +1272,7 @@ init_threadstate(PyThreadState *tstate,
tstate->datastack_chunk = NULL;
tstate->datastack_top = NULL;
tstate->datastack_limit = NULL;
+ tstate->what_event = -1;
tstate->_status.initialized = 1;
}
@@ -1424,8 +1448,14 @@ PyThreadState_Clear(PyThreadState *tstate)
"PyThreadState_Clear: warning: thread still has a generator\n");
}
- tstate->c_profilefunc = NULL;
- tstate->c_tracefunc = NULL;
+ if (tstate->c_profilefunc != NULL) {
+ tstate->interp->sys_profiling_threads--;
+ tstate->c_profilefunc = NULL;
+ }
+ if (tstate->c_tracefunc != NULL) {
+ tstate->interp->sys_tracing_threads--;
+ tstate->c_tracefunc = NULL;
+ }
Py_CLEAR(tstate->c_profileobj);
Py_CLEAR(tstate->c_traceobj);
diff --git a/Python/specialize.c b/Python/specialize.c
index a9d3226ee39f5f..3fa28f409892dc 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -273,7 +273,8 @@ _PyCode_Quicken(PyCodeObject *code)
_Py_CODEUNIT *instructions = _PyCode_CODE(code);
for (int i = 0; i < Py_SIZE(code); i++) {
int previous_opcode = opcode;
- opcode = _PyOpcode_Deopt[instructions[i].op.code];
+ opcode = _Py_GetBaseOpcode(code, i);
+ assert(opcode < MIN_INSTRUMENTED_OPCODE);
int caches = _PyOpcode_Caches[opcode];
if (caches) {
instructions[i + 1].cache = adaptive_counter_warmup();
@@ -1737,6 +1738,7 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
{
assert(ENABLE_SPECIALIZATION);
assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
+ assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
int fail;
if (PyCFunction_CheckExact(callable)) {
@@ -2149,7 +2151,9 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)
goto success;
}
else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
- assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR);
+ assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
+ instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
+ );
instr->op.code = FOR_ITER_GEN;
goto success;
}
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index f1a294de598420..4d693a1be1f89e 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -3409,6 +3409,7 @@ _PySys_SetPreliminaryStderr(PyObject *sysdict)
return _PyStatus_ERR("can't set preliminary stderr");
}
+PyObject *_Py_CreateMonitoringObject(void);
/* Create sys module without all attributes.
_PySys_UpdateConfig() should be called later to add remaining attributes. */
@@ -3458,6 +3459,16 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
goto error;
}
+ PyObject *monitoring = _Py_CreateMonitoringObject();
+ if (monitoring == NULL) {
+ goto error;
+ }
+ int err = PyDict_SetItemString(sysdict, "monitoring", monitoring);
+ Py_DECREF(monitoring);
+ if (err < 0) {
+ goto error;
+ }
+
assert(!_PyErr_Occurred(tstate));
*sysmod_p = sysmod;
diff --git a/Tools/build/deepfreeze.py b/Tools/build/deepfreeze.py
index ec808526b7bbb7..aba5fecd8b1a99 100644
--- a/Tools/build/deepfreeze.py
+++ b/Tools/build/deepfreeze.py
@@ -255,7 +255,6 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.write(f".co_names = {co_names},")
self.write(f".co_exceptiontable = {co_exceptiontable},")
self.field(code, "co_flags")
- self.write("._co_linearray_entry_size = 0,")
self.field(code, "co_argcount")
self.field(code, "co_posonlyargcount")
self.field(code, "co_kwonlyargcount")
@@ -276,7 +275,6 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.write(f".co_qualname = {co_qualname},")
self.write(f".co_linetable = {co_linetable},")
self.write(f"._co_cached = NULL,")
- self.write("._co_linearray = NULL,")
self.write(f".co_code_adaptive = {co_code_adaptive},")
for i, op in enumerate(code.co_code[::2]):
if op == RESUME:
diff --git a/Tools/build/generate_opcode_h.py b/Tools/build/generate_opcode_h.py
index 614b17df740929..ccf3c5673c4e18 100644
--- a/Tools/build/generate_opcode_h.py
+++ b/Tools/build/generate_opcode_h.py
@@ -89,6 +89,7 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
HAVE_ARGUMENT = opcode["HAVE_ARGUMENT"]
MIN_PSEUDO_OPCODE = opcode["MIN_PSEUDO_OPCODE"]
MAX_PSEUDO_OPCODE = opcode["MAX_PSEUDO_OPCODE"]
+ MIN_INSTRUMENTED_OPCODE = opcode["MIN_INSTRUMENTED_OPCODE"]
NUM_OPCODES = len(opname)
used = [ False ] * len(opname)
@@ -105,9 +106,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
specialized_opmap[name] = next_op
opname_including_specialized[next_op] = name
used[next_op] = True
- specialized_opmap['DO_TRACING'] = 255
- opname_including_specialized[255] = 'DO_TRACING'
- used[255] = True
with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj:
fobj.write(header)
@@ -120,6 +118,8 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
fobj.write(DEFINE.format("HAVE_ARGUMENT", HAVE_ARGUMENT))
if op == MIN_PSEUDO_OPCODE:
fobj.write(DEFINE.format("MIN_PSEUDO_OPCODE", MIN_PSEUDO_OPCODE))
+ if op == MIN_INSTRUMENTED_OPCODE:
+ fobj.write(DEFINE.format("MIN_INSTRUMENTED_OPCODE", MIN_INSTRUMENTED_OPCODE))
fobj.write(DEFINE.format(name, op))
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 0620c7e13925b5..8745f8abc224fe 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -135,6 +135,9 @@ Objects/stringlib/unicode_format.h - PyFieldNameIter_Type -
Objects/unicodeobject.c - EncodingMapType -
#Objects/unicodeobject.c - PyFieldNameIter_Type -
#Objects/unicodeobject.c - PyFormatterIter_Type -
+Python/legacy_tracing.c - _PyLegacyEventHandler_Type -
+Objects/object.c - _PyLegacyEventHandler_Type -
+
##-----------------------
## static builtin structseq
@@ -297,6 +300,8 @@ Objects/object.c - _Py_NotImplementedStruct -
Objects/setobject.c - _dummy_struct -
Objects/setobject.c - _PySet_Dummy -
Objects/sliceobject.c - _Py_EllipsisObject -
+Python/instrumentation.c - DISABLE -
+Python/instrumentation.c - _PyInstrumentation_MISSING -
##################################
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy