Skip to content

bpo-46072: Merge dxpairs into py_stats. #31197

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Opcode pair stats are now gathered with ``--enable-pystats``. Defining
``DYNAMIC_EXECUTION_PROFILE`` or ``DXPAIRS`` no longer has any effect.
77 changes: 17 additions & 60 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,6 @@ _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame *frame);
"cannot access free variable '%s' where it is not associated with a" \
" value in enclosing scope"

/* Dynamic execution profile */
#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef DXPAIRS
static long dxpairs[257][256];
#define dxp dxpairs[256]
#else
static long dxp[256];
#endif
#endif

#ifndef NDEBUG
/* Ensure that tstate is valid: sanity check for PyEval_AcquireThread() and
PyEval_RestoreThread(). Detect if tstate memory was freed. It can happen
Expand Down Expand Up @@ -1239,10 +1229,6 @@ eval_frame_handle_pending(PyThreadState *tstate)
faster than the normal "switch" version, depending on the compiler and the
CPU architecture.

We disable the optimization if DYNAMIC_EXECUTION_PROFILE is defined,
because it would render the measurements invalid.


NOTE: care must be taken that the compiler doesn't try to "optimize" the
indirect jumps by sharing them between all opcodes. Such optimizations
can be disabled on gcc by using the -fno-gcse flag (or possibly
Expand All @@ -1254,23 +1240,13 @@ eval_frame_handle_pending(PyThreadState *tstate)
* We want to be sure that the compiler knows this before it generates
* the CFG.
*/
#ifdef LLTRACE
#define LLTRACE_INSTR() if (lltrace) { lltrace_instruction(frame, opcode, oparg); }
#else
#define LLTRACE_INSTR() ((void)0)
#endif

#ifdef WITH_DTRACE
#define OR_DTRACE_LINE | (PyDTrace_LINE_ENABLED() ? 255 : 0)
#else
#define OR_DTRACE_LINE
#endif

#ifdef DYNAMIC_EXECUTION_PROFILE
#undef USE_COMPUTED_GOTOS
#define USE_COMPUTED_GOTOS 0
#endif

#ifdef HAVE_COMPUTED_GOTOS
#ifndef USE_COMPUTED_GOTOS
#define USE_COMPUTED_GOTOS 1
Expand All @@ -1284,7 +1260,14 @@ eval_frame_handle_pending(PyThreadState *tstate)
#endif

#ifdef Py_STATS
#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++; OPCODE_EXE_INC(op);
#define INSTRUCTION_START(op) \
do { \
frame->f_lasti = INSTR_OFFSET(); \
next_instr++; \
OPCODE_EXE_INC(op); \
_py_stats.opcode_stats[lastopcode].pair_count[op]++; \
lastopcode = op; \
} while (0)
#else
#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++
#endif
Expand All @@ -1297,34 +1280,12 @@ eval_frame_handle_pending(PyThreadState *tstate)
#define DISPATCH_GOTO() goto dispatch_opcode
#endif

/* RECORD_DXPROFILE() records the dxprofile information, if enabled. Normally a no-op */
#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef DXPAIRS
#define RECORD_DXPROFILE() \
do { \
dxpairs[lastopcode][opcode]++; \
lastopcode = opcode; \
dxp[opcode]++; \
} while (0)
#else
#define RECORD_DXPROFILE() \
do { \
dxp[opcode]++; \
} while (0)
#endif
/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
#ifdef LLTRACE
#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(frame, opcode, oparg); }
#else
#define RECORD_DXPROFILE() ((void)0)
#endif

/* PRE_DISPATCH_GOTO() does lltrace and dxprofile if either is enabled. Normally a no-op */
#ifndef LLTRACE
#ifndef DYNAMIC_EXECUTION_PROFILE
#define PRE_DISPATCH_GOTO() ((void)0)
#endif
#endif
#ifndef PRE_DISPATCH_GOTO
#define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR(); RECORD_DXPROFILE(); } while (0)
#endif

#define NOTRACE_DISPATCH() \
{ \
Expand Down Expand Up @@ -1404,7 +1365,7 @@ eval_frame_handle_pending(PyThreadState *tstate)

#define PREDICT_ID(op) PRED_##op

#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
#if USE_COMPUTED_GOTOS
#define PREDICT(op) if (0) goto PREDICT_ID(op)
#else
#define PREDICT(op) \
Expand Down Expand Up @@ -1658,7 +1619,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
#include "opcode_targets.h"
#endif

#ifdef DXPAIRS
#ifdef Py_STATS
int lastopcode = 0;
#endif
int opcode; /* Current opcode */
Expand Down Expand Up @@ -7487,16 +7448,16 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevpr
}
}

#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef Py_STATS

static PyObject *
getarray(long a[256])
getarray(uint64_t a[256])
{
int i;
PyObject *l = PyList_New(256);
if (l == NULL) return NULL;
for (i = 0; i < 256; i++) {
PyObject *x = PyLong_FromLong(a[i]);
PyObject *x = PyLong_FromUnsignedLongLong(a[i]);
if (x == NULL) {
Py_DECREF(l);
return NULL;
Expand All @@ -7511,22 +7472,18 @@ getarray(long a[256])
PyObject *
_Py_GetDXProfile(PyObject *self, PyObject *args)
{
#ifndef DXPAIRS
return getarray(dxp);
#else
int i;
PyObject *l = PyList_New(257);
if (l == NULL) return NULL;
for (i = 0; i < 257; i++) {
PyObject *x = getarray(dxpairs[i]);
PyObject *x = getarray(_py_stats.opcode_stats[i].pair_count);
if (x == NULL) {
Py_DECREF(l);
return NULL;
}
PyList_SET_ITEM(l, i, x);
}
return l;
#endif
}

#endif
Expand Down
4 changes: 2 additions & 2 deletions Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ sys__debugmallocstats_impl(PyObject *module)
extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
#endif

#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef Py_STATS
/* Defined in ceval.c because it uses static globals in that file */
extern PyObject *_Py_GetDXProfile(PyObject *, PyObject *);
#endif
Expand Down Expand Up @@ -1992,7 +1992,7 @@ static PyMethodDef sys_methods[] = {
SYS_GETDEFAULTENCODING_METHODDEF
SYS_GETDLOPENFLAGS_METHODDEF
SYS_GETALLOCATEDBLOCKS_METHODDEF
#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef Py_STATS
{"getdxp", _Py_GetDXProfile, METH_VARARGS},
#endif
SYS_GETFILESYSTEMENCODING_METHODDEF
Expand Down