commit 1e399f5ec381276b52e6a4f5a755fc0f23bd6d97 Author: Peter McCormick Date: Fri Jul 27 01:19:16 2018 -0400 Generalize PyDTrace to PyProbe diff --git a/Include/pydtrace.d b/Include/pydtrace.d index a6a5e7ec22..c68a97301e 100644 --- a/Include/pydtrace.d +++ b/Include/pydtrace.d @@ -6,7 +6,7 @@ provider python { probe instance__new__start(const char *, const char *); probe instance__new__done(const char *, const char *); probe instance__delete__start(const char *, const char *); - probe instance__delete__done(const char *, const char *); + probe instance__delete__done(const char *, int); probe line(const char *, const char *, int); probe gc__start(int); probe gc__done(long); diff --git a/Include/pydtrace.h b/Include/pydtrace.h index 037961d429..720a87f60b 100644 --- a/Include/pydtrace.h +++ b/Include/pydtrace.h @@ -30,10 +30,10 @@ static inline void PyDTrace_FUNCTION_ENTRY(const char *arg0, const char *arg1, i static inline void PyDTrace_FUNCTION_RETURN(const char *arg0, const char *arg1, int arg2) {} static inline void PyDTrace_GC_START(int arg0) {} static inline void PyDTrace_GC_DONE(int arg0) {} -static inline void PyDTrace_INSTANCE_NEW_START(int arg0) {} -static inline void PyDTrace_INSTANCE_NEW_DONE(int arg0) {} -static inline void PyDTrace_INSTANCE_DELETE_START(int arg0) {} -static inline void PyDTrace_INSTANCE_DELETE_DONE(int arg0) {} +static inline void PyDTrace_INSTANCE_NEW_START(const char *arg, const char *arg1) {} +static inline void PyDTrace_INSTANCE_NEW_DONE(const char *arg0, const char *arg1) {} +static inline void PyDTrace_INSTANCE_DELETE_START(const char *arg0, const char *arg1) {} +static inline void PyDTrace_INSTANCE_DELETE_DONE(const char *arg0, int arg1) {} static inline void PyDTrace_IMPORT_FIND_LOAD_START(const char *arg0) {} static inline void PyDTrace_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) {} diff --git a/Include/pyprobe.h b/Include/pyprobe.h new file mode 100644 index 0000000000..7c9879c33e --- /dev/null +++ b/Include/pyprobe.h @@ -0,0 +1,277 @@ +#ifndef Py_PROBE_H +#define Py_PROBE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WITH_DTRACE +#define WITH_PYPROBE +#endif + +#ifdef WITH_PYPROBE + +/* pydtrace_probes.h, on systems with DTrace, is auto-generated to include + `PyDTrace_{PROBE}` and `PyDTrace_{PROBE}_ENABLED()` macros for every probe + defined in pydtrace_provider.d. + + Calling these functions must be guarded by a `PyDTrace_{PROBE}_ENABLED()` + check to minimize performance impact when probing is off. For example: + + if (PyDTrace_FUNCTION_ENTRY_ENABLED()) + PyDTrace_FUNCTION_ENTRY(f); +*/ + +#ifdef WITH_DTRACE +#include "pydtrace_probes.h" +#endif /* WITH_DTRACE */ + +static inline void +PyProbe_LINE(const char *arg0, const char *arg1, int arg2) +{ + (void)arg0; + (void)arg1; + (void)arg2; + + if (PyDTrace_LINE_ENABLED()) { + PyDTrace_LINE(arg0, arg1, arg2); + } +} + +static inline void +PyProbe_FUNCTION_ENTRY(const char *arg0, const char *arg1, int arg2) +{ + (void)arg0; + (void)arg1; + (void)arg2; + + if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { + PyDTrace_FUNCTION_ENTRY(arg0, arg1, arg2); + } +} + +static inline void +PyProbe_FUNCTION_RETURN(const char *arg0, const char *arg1, int arg2) +{ + (void)arg0; + (void)arg1; + (void)arg2; + + if (PyDTrace_FUNCTION_RETURN_ENABLED()) { + PyDTrace_FUNCTION_RETURN(arg0, arg1, arg2); + } +} + +static inline void +PyProbe_GC_START(int arg0) +{ + (void)arg0; + + if (PyDTrace_GC_START_ENABLED()) { + PyDTrace_GC_START(arg0); + } +} + +static inline void +PyProbe_GC_DONE(long arg0) +{ + (void)arg0; + + if (PyDTrace_GC_DONE_ENABLED()) { + PyDTrace_GC_DONE(arg0); + } +} + +static inline void +PyProbe_INSTANCE_NEW_START(const char *arg0, const char *arg1) +{ + (void)arg0; + + if (PyDTrace_INSTANCE_NEW_START_ENABLED()) { + PyDTrace_INSTANCE_NEW_START(arg0, arg1); + } +} + +static inline void +PyProbe_INSTANCE_NEW_DONE(const char *arg0, const char *arg1) +{ + (void)arg0; + + if (PyDTrace_INSTANCE_NEW_DONE_ENABLED()) { + PyDTrace_INSTANCE_NEW_DONE(arg0, arg1); + } +} + +static inline void +PyProbe_INSTANCE_DELETE_START(const char *arg0, const char *arg1) +{ + (void)arg0; + + if (PyDTrace_INSTANCE_DELETE_START_ENABLED()) { + PyDTrace_INSTANCE_DELETE_START(arg0, arg1); + } +} + +static inline void +PyProbe_INSTANCE_DELETE_DONE(const char *arg0, int arg1) +{ + (void)arg0; + + if (PyDTrace_INSTANCE_DELETE_DONE_ENABLED()) { + PyDTrace_INSTANCE_DELETE_DONE(arg0, arg1); + } +} + +static inline void +PyProbe_IMPORT_FIND_LOAD_START(const char *arg0) +{ + (void)arg0; + + if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()) { + PyDTrace_IMPORT_FIND_LOAD_START(arg0); + } +} + +static inline void +PyProbe_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) +{ + (void)arg0; + (void)arg1; + + if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED()) { + PyDTrace_IMPORT_FIND_LOAD_DONE(arg0, arg1); + } +} + +static inline int PyProbe_LINE_ENABLED(void) +{ + if (PyDTrace_LINE_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_FUNCTION_ENTRY_ENABLED(void) +{ + if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_FUNCTION_RETURN_ENABLED(void) +{ + if (PyDTrace_FUNCTION_RETURN_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_GC_START_ENABLED(void) +{ + if (PyDTrace_GC_START_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_GC_DONE_ENABLED(void) +{ + if (PyDTrace_GC_DONE_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_INSTANCE_NEW_START_ENABLED(void) +{ + if (PyDTrace_INSTANCE_NEW_START_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_INSTANCE_NEW_DONE_ENABLED(void) +{ + if (PyDTrace_INSTANCE_NEW_DONE_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_INSTANCE_DELETE_START_ENABLED(void) +{ + if (PyDTrace_INSTANCE_DELETE_START_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_INSTANCE_DELETE_DONE_ENABLED(void) +{ + if (PyDTrace_INSTANCE_DELETE_DONE_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_IMPORT_FIND_LOAD_START_ENABLED(void) +{ + if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()) { + return 1; + } + + return 0; +} + +static inline int PyProbe_IMPORT_FIND_LOAD_DONE_ENABLED(void) +{ + if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED()) { + return 1; + } + + return 0; +} + +#else + +/* Without probing enabled, compile to nothing. */ + +#define PyProbe_LINE(arg0, arg1, arg2) +#define PyProbe_FUNCTION_ENTRY(arg0, arg1, arg2) +#define PyProbe_FUNCTION_RETURN(arg0, arg1, arg2) +#define PyProbe_GC_START(arg0) +#define PyProbe_GC_DONE(arg0) +#define PyProbe_INSTANCE_NEW_START(arg0, arg1) +#define PyProbe_INSTANCE_NEW_DONE(arg0, arg1) +#define PyProbe_INSTANCE_DELETE_START(arg0, arg1) +#define PyProbe_INSTANCE_DELETE_DONE(arg0, arg1) +#define PyProbe_IMPORT_FIND_LOAD_START(arg0) +#define PyProbe_IMPORT_FIND_LOAD_DONE(arg0, arg1) + +#define PyProbe_LINE_ENABLED() (0) +#define PyProbe_FUNCTION_ENTRY_ENABLED() (0) +#define PyProbe_FUNCTION_RETURN_ENABLED() (0) +#define PyProbe_GC_START_ENABLED() (0) +#define PyProbe_GC_DONE_ENABLED() (0) +#define PyProbe_INSTANCE_NEW_START_ENABLED() (0) +#define PyProbe_INSTANCE_NEW_DONE_ENABLED() (0) +#define PyProbe_INSTANCE_DELETE_START_ENABLED() (0) +#define PyProbe_INSTANCE_DELETE_DONE_ENABLED() (0) +#define PyProbe_IMPORT_FIND_LOAD_START_ENABLED() (0) +#define PyProbe_IMPORT_FIND_LOAD_DONE_ENABLED() (0) + +#endif /* !WITH_PYPROBE */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PROBE_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index 51cf2fdb00..a852dc2da1 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -985,6 +985,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/pyctype.h \ $(srcdir)/Include/pydebug.h \ $(srcdir)/Include/pydtrace.h \ + $(srcdir)/Include/pyprobe.h \ $(srcdir)/Include/pyerrors.h \ $(srcdir)/Include/pyfpe.h \ $(srcdir)/Include/pyhash.h \ diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index e3e290cf97..a9786fab42 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -28,7 +28,7 @@ #include "internal/mem.h" #include "internal/pystate.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ -#include "pydtrace.h" +#include "pyprobe.h" #include "pytime.h" /* for _PyTime_GetMonotonicClock() */ /*[clinic input] @@ -983,8 +983,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, PySys_WriteStderr("\n"); } - if (PyDTrace_GC_START_ENABLED()) - PyDTrace_GC_START(generation); + PyProbe_GC_START(generation); /* update collection and allocation counters */ if (generation+1 < NUM_GENERATIONS) @@ -1140,8 +1139,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, stats->collected += m; stats->uncollectable += n; - if (PyDTrace_GC_DONE_ENABLED()) - PyDTrace_GC_DONE(n+m); + PyProbe_GC_DONE(n+m); assert(!PyErr_Occurred()); return n+m; diff --git a/Python/ceval.c b/Python/ceval.c index 8f0e0e00c2..82afc6cad1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -16,7 +16,7 @@ #include "dictobject.h" #include "frameobject.h" #include "opcode.h" -#include "pydtrace.h" +#include "pyprobe.h" #include "setobject.h" #include "structmember.h" @@ -53,9 +53,9 @@ static void call_exc_trace(Py_tracefunc, PyObject *, static int maybe_call_line_trace(Py_tracefunc, PyObject *, PyThreadState *, PyFrameObject *, int *, int *, int *); -static void maybe_dtrace_line(PyFrameObject *, int *, int *, int *); -static void dtrace_function_entry(PyFrameObject *); -static void dtrace_function_return(PyFrameObject *); +static void maybe_probe_line(PyFrameObject *, int *, int *, int *); +static void probe_function_entry(PyFrameObject *); +static void probe_function_return(PyFrameObject *); static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_name(PyFrameObject *, PyObject *, PyObject *, @@ -643,7 +643,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) #ifdef LLTRACE #define FAST_DISPATCH() \ { \ - if (!lltrace && !_Py_TracingPossible && !PyDTrace_LINE_ENABLED()) { \ + if (!lltrace && !_Py_TracingPossible && !PyProbe_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ NEXTOPARG(); \ goto *opcode_targets[opcode]; \ @@ -653,7 +653,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) #else #define FAST_DISPATCH() \ { \ - if (!_Py_TracingPossible && !PyDTrace_LINE_ENABLED()) { \ + if (!_Py_TracingPossible && !PyProbe_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ NEXTOPARG(); \ goto *opcode_targets[opcode]; \ @@ -859,8 +859,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } } - if (PyDTrace_FUNCTION_ENTRY_ENABLED()) - dtrace_function_entry(f); + if (PyProbe_FUNCTION_ENTRY_ENABLED()) + probe_function_entry(f); co = f->f_code; names = co->co_names; @@ -994,8 +994,8 @@ main_loop: fast_next_opcode: f->f_lasti = INSTR_OFFSET(); - if (PyDTrace_LINE_ENABLED()) - maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev); + if (PyProbe_LINE_ENABLED()) + maybe_probe_line(f, &instr_lb, &instr_ub, &instr_prev); /* line-by-line tracing support */ @@ -3502,8 +3502,8 @@ return_or_yield: /* pop frame */ exit_eval_frame: - if (PyDTrace_FUNCTION_RETURN_ENABLED()) - dtrace_function_return(f); + if (PyProbe_FUNCTION_RETURN_ENABLED()) + probe_function_return(f); Py_LeaveRecursiveCall(); f->f_executing = 0; tstate->frame = f->f_back; @@ -5138,7 +5138,7 @@ _PyEval_RequestCodeExtraIndex(freefunc free) } static void -dtrace_function_entry(PyFrameObject *f) +probe_function_entry(PyFrameObject *f) { const char *filename; const char *funcname; @@ -5148,11 +5148,11 @@ dtrace_function_entry(PyFrameObject *f) funcname = PyUnicode_AsUTF8(f->f_code->co_name); lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); - PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno); + PyProbe_FUNCTION_ENTRY(filename, funcname, lineno); } static void -dtrace_function_return(PyFrameObject *f) +probe_function_return(PyFrameObject *f) { const char *filename; const char *funcname; @@ -5162,12 +5162,12 @@ dtrace_function_return(PyFrameObject *f) funcname = PyUnicode_AsUTF8(f->f_code->co_name); lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); - PyDTrace_FUNCTION_RETURN(filename, funcname, lineno); + PyProbe_FUNCTION_RETURN(filename, funcname, lineno); } /* DTrace equivalent of maybe_call_line_trace. */ static void -maybe_dtrace_line(PyFrameObject *frame, +maybe_probe_line(PyFrameObject *frame, int *instr_lb, int *instr_ub, int *instr_prev) { int line = frame->f_lineno; @@ -5194,7 +5194,7 @@ maybe_dtrace_line(PyFrameObject *frame, co_name = PyUnicode_AsUTF8(frame->f_code->co_name); if (!co_name) co_name = "?"; - PyDTrace_LINE(co_filename, co_name, line); + PyProbe_LINE(co_filename, co_name, line); } *instr_prev = frame->f_lasti; } diff --git a/Python/import.c b/Python/import.c index 3a59183665..62f5edb593 100644 --- a/Python/import.c +++ b/Python/import.c @@ -13,7 +13,7 @@ #include "frameobject.h" #include "osdefs.h" #include "importdl.h" -#include "pydtrace.h" +#include "pyprobe.h" #ifdef HAVE_FCNTL_H #include @@ -1645,16 +1645,13 @@ import_find_and_load(PyObject *abs_name) accumulated = 0; } - if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()) - PyDTrace_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name)); + PyProbe_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name)); mod = _PyObject_CallMethodIdObjArgs(interp->importlib, &PyId__find_and_load, abs_name, interp->import_func, NULL); - if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED()) - PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name), - mod != NULL); + PyProbe_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name), mod != NULL); if (import_time) { _PyTime_t cum = _PyTime_GetPerfCounter() - t1;