bpo-46072: Merge dxpairs into py_stats. (GH-31197)

This commit is contained in:
Mark Shannon 2022-02-07 16:51:43 +00:00 committed by GitHub
parent a89772c791
commit 9c979d7afd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 62 deletions

View File

@ -0,0 +1,2 @@
Opcode pair stats are now gathered with ``--enable-pystats``. Defining
``DYNAMIC_EXECUTION_PROFILE`` or ``DXPAIRS`` no longer has any effect.

View File

@ -114,16 +114,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
@ -1238,10 +1228,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
@ -1253,11 +1239,6 @@ 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)
@ -1265,11 +1246,6 @@ eval_frame_handle_pending(PyThreadState *tstate)
#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
@ -1283,7 +1259,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
@ -1296,34 +1279,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)
/* 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() \
do { \
dxp[opcode]++; \
} while (0)
#endif
#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() \
{ \
@ -1403,7 +1364,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) \
@ -1653,7 +1614,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 */
@ -7489,16 +7450,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;
@ -7513,14 +7474,11 @@ 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;
@ -7528,7 +7486,6 @@ _Py_GetDXProfile(PyObject *self, PyObject *args)
PyList_SET_ITEM(l, i, x);
}
return l;
#endif
}
#endif

View File

@ -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
@ -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