Skip to content

Commit 9c979d7

Browse files
authored
bpo-46072: Merge dxpairs into py_stats. (GH-31197)
1 parent a89772c commit 9c979d7

File tree

3 files changed

+21
-62
lines changed

3 files changed

+21
-62
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Opcode pair stats are now gathered with ``--enable-pystats``. Defining
2+
``DYNAMIC_EXECUTION_PROFILE`` or ``DXPAIRS`` no longer has any effect.

Python/ceval.c

+17-60
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,6 @@ _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame *frame);
114114
"cannot access free variable '%s' where it is not associated with a" \
115115
" value in enclosing scope"
116116

117-
/* Dynamic execution profile */
118-
#ifdef DYNAMIC_EXECUTION_PROFILE
119-
#ifdef DXPAIRS
120-
static long dxpairs[257][256];
121-
#define dxp dxpairs[256]
122-
#else
123-
static long dxp[256];
124-
#endif
125-
#endif
126-
127117
#ifndef NDEBUG
128118
/* Ensure that tstate is valid: sanity check for PyEval_AcquireThread() and
129119
PyEval_RestoreThread(). Detect if tstate memory was freed. It can happen
@@ -1238,10 +1228,6 @@ eval_frame_handle_pending(PyThreadState *tstate)
12381228
faster than the normal "switch" version, depending on the compiler and the
12391229
CPU architecture.
12401230
1241-
We disable the optimization if DYNAMIC_EXECUTION_PROFILE is defined,
1242-
because it would render the measurements invalid.
1243-
1244-
12451231
NOTE: care must be taken that the compiler doesn't try to "optimize" the
12461232
indirect jumps by sharing them between all opcodes. Such optimizations
12471233
can be disabled on gcc by using the -fno-gcse flag (or possibly
@@ -1253,23 +1239,13 @@ eval_frame_handle_pending(PyThreadState *tstate)
12531239
* We want to be sure that the compiler knows this before it generates
12541240
* the CFG.
12551241
*/
1256-
#ifdef LLTRACE
1257-
#define LLTRACE_INSTR() if (lltrace) { lltrace_instruction(frame, opcode, oparg); }
1258-
#else
1259-
#define LLTRACE_INSTR() ((void)0)
1260-
#endif
12611242

12621243
#ifdef WITH_DTRACE
12631244
#define OR_DTRACE_LINE | (PyDTrace_LINE_ENABLED() ? 255 : 0)
12641245
#else
12651246
#define OR_DTRACE_LINE
12661247
#endif
12671248

1268-
#ifdef DYNAMIC_EXECUTION_PROFILE
1269-
#undef USE_COMPUTED_GOTOS
1270-
#define USE_COMPUTED_GOTOS 0
1271-
#endif
1272-
12731249
#ifdef HAVE_COMPUTED_GOTOS
12741250
#ifndef USE_COMPUTED_GOTOS
12751251
#define USE_COMPUTED_GOTOS 1
@@ -1283,7 +1259,14 @@ eval_frame_handle_pending(PyThreadState *tstate)
12831259
#endif
12841260

12851261
#ifdef Py_STATS
1286-
#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++; OPCODE_EXE_INC(op);
1262+
#define INSTRUCTION_START(op) \
1263+
do { \
1264+
frame->f_lasti = INSTR_OFFSET(); \
1265+
next_instr++; \
1266+
OPCODE_EXE_INC(op); \
1267+
_py_stats.opcode_stats[lastopcode].pair_count[op]++; \
1268+
lastopcode = op; \
1269+
} while (0)
12871270
#else
12881271
#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++
12891272
#endif
@@ -1296,34 +1279,12 @@ eval_frame_handle_pending(PyThreadState *tstate)
12961279
#define DISPATCH_GOTO() goto dispatch_opcode
12971280
#endif
12981281

1299-
/* RECORD_DXPROFILE() records the dxprofile information, if enabled. Normally a no-op */
1300-
#ifdef DYNAMIC_EXECUTION_PROFILE
1301-
#ifdef DXPAIRS
1302-
#define RECORD_DXPROFILE() \
1303-
do { \
1304-
dxpairs[lastopcode][opcode]++; \
1305-
lastopcode = opcode; \
1306-
dxp[opcode]++; \
1307-
} while (0)
1308-
#else
1309-
#define RECORD_DXPROFILE() \
1310-
do { \
1311-
dxp[opcode]++; \
1312-
} while (0)
1313-
#endif
1282+
/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
1283+
#ifdef LLTRACE
1284+
#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(frame, opcode, oparg); }
13141285
#else
1315-
#define RECORD_DXPROFILE() ((void)0)
1316-
#endif
1317-
1318-
/* PRE_DISPATCH_GOTO() does lltrace and dxprofile if either is enabled. Normally a no-op */
1319-
#ifndef LLTRACE
1320-
#ifndef DYNAMIC_EXECUTION_PROFILE
13211286
#define PRE_DISPATCH_GOTO() ((void)0)
13221287
#endif
1323-
#endif
1324-
#ifndef PRE_DISPATCH_GOTO
1325-
#define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR(); RECORD_DXPROFILE(); } while (0)
1326-
#endif
13271288

13281289
#define NOTRACE_DISPATCH() \
13291290
{ \
@@ -1403,7 +1364,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
14031364

14041365
#define PREDICT_ID(op) PRED_##op
14051366

1406-
#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
1367+
#if USE_COMPUTED_GOTOS
14071368
#define PREDICT(op) if (0) goto PREDICT_ID(op)
14081369
#else
14091370
#define PREDICT(op) \
@@ -1653,7 +1614,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
16531614
#include "opcode_targets.h"
16541615
#endif
16551616

1656-
#ifdef DXPAIRS
1617+
#ifdef Py_STATS
16571618
int lastopcode = 0;
16581619
#endif
16591620
int opcode; /* Current opcode */
@@ -7489,16 +7450,16 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevpr
74897450
}
74907451
}
74917452

7492-
#ifdef DYNAMIC_EXECUTION_PROFILE
7453+
#ifdef Py_STATS
74937454

74947455
static PyObject *
7495-
getarray(long a[256])
7456+
getarray(uint64_t a[256])
74967457
{
74977458
int i;
74987459
PyObject *l = PyList_New(256);
74997460
if (l == NULL) return NULL;
75007461
for (i = 0; i < 256; i++) {
7501-
PyObject *x = PyLong_FromLong(a[i]);
7462+
PyObject *x = PyLong_FromUnsignedLongLong(a[i]);
75027463
if (x == NULL) {
75037464
Py_DECREF(l);
75047465
return NULL;
@@ -7513,22 +7474,18 @@ getarray(long a[256])
75137474
PyObject *
75147475
_Py_GetDXProfile(PyObject *self, PyObject *args)
75157476
{
7516-
#ifndef DXPAIRS
7517-
return getarray(dxp);
7518-
#else
75197477
int i;
75207478
PyObject *l = PyList_New(257);
75217479
if (l == NULL) return NULL;
75227480
for (i = 0; i < 257; i++) {
7523-
PyObject *x = getarray(dxpairs[i]);
7481+
PyObject *x = getarray(_py_stats.opcode_stats[i].pair_count);
75247482
if (x == NULL) {
75257483
Py_DECREF(l);
75267484
return NULL;
75277485
}
75287486
PyList_SET_ITEM(l, i, x);
75297487
}
75307488
return l;
7531-
#endif
75327489
}
75337490

75347491
#endif

Python/sysmodule.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1923,7 +1923,7 @@ sys__debugmallocstats_impl(PyObject *module)
19231923
extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
19241924
#endif
19251925

1926-
#ifdef DYNAMIC_EXECUTION_PROFILE
1926+
#ifdef Py_STATS
19271927
/* Defined in ceval.c because it uses static globals in that file */
19281928
extern PyObject *_Py_GetDXProfile(PyObject *, PyObject *);
19291929
#endif
@@ -1992,7 +1992,7 @@ static PyMethodDef sys_methods[] = {
19921992
SYS_GETDEFAULTENCODING_METHODDEF
19931993
SYS_GETDLOPENFLAGS_METHODDEF
19941994
SYS_GETALLOCATEDBLOCKS_METHODDEF
1995-
#ifdef DYNAMIC_EXECUTION_PROFILE
1995+
#ifdef Py_STATS
19961996
{"getdxp", _Py_GetDXProfile, METH_VARARGS},
19971997
#endif
19981998
SYS_GETFILESYSTEMENCODING_METHODDEF

0 commit comments

Comments
 (0)