8000 GH-91719: Make MSVC generate somewhat faster switch code (#91718) · python/cpython@f8dc618 · GitHub
[go: up one dir, main page]

Skip to content

Commit f8dc618

Browse files
authored
GH-91719: Make MSVC generate somewhat faster switch code (#91718)
Apparently a switch on an 8-bit quantity where all cases are present generates a more efficient jump (doing only one indexed memory load instead of two). So we make opcode and use_tracing uint8_t, and generate a macro full of extra `case NNN:` lines for all unused opcodes. See faster-cpython/ideas#321 (comment)
1 parent d44815c commit f8dc618

File tree

4 files changed

+90
-3
lines changed

4 files changed

+90
-3
lines changed

Include/cpython/pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ typedef struct _PyCFrame {
4646
* discipline and make sure that instances of this struct cannot
4747
* accessed outside of their lifetime.
4848
*/
49-
int use_tracing;
49+
uint8_t use_tracing; // 0 or 255 (or'ed into opcode, hence 8-bit type)
5050
/* Pointer to the currently executing frame (it can be NULL) */
5151
struct _PyInterpreterFrame *current_frame;
5252
struct _PyCFrame *previous;

Include/opcode.h

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/ceval.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
16621662
#ifdef Py_STATS
16631663
int lastopcode = 0;
16641664
#endif
1665-
int opcode; /* Current opcode */
1665+
// opcode is an 8-bit value to improve the code generated by MSVC
1666+
// for the big switch below (in combination with the EXTRA_CASES macro).
1667+
uint8_t opcode; /* Current opcode */
16661668
int oparg; /* Current opcode argument, if any */
16671669
_Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker;
16681670

@@ -5645,7 +5647,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
56455647
#if USE_COMPUTED_GOTOS
56465648
_unknown_opcode:
56475649
#else
5648-
default:
5650+
EXTRA_CASES // From opcode.h, a 'case' for each unused opcode
56495651
#endif
56505652
fprintf(stderr, "XXX lineno: %d, opcode: %d\n",
56515653
_PyInterpreterFrame_GetLine(frame), opcode);

Tools/scripts/generate_opcode_h.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ def main(opcode_py, outfile='Include/opcode.h'):
129129
fobj.write("};\n")
130130
fobj.write("#endif\n")
131131

132+
fobj.write("\n")
133+
fobj.write("#define EXTRA_CASES \\\n")
134+
for i, flag in enumerate(used):
135+
if not flag:
136+
fobj.write(f" case {i}: \\\n")
137+
fobj.write(" ;\n")
138+
132139
fobj.write(footer)
133140

134141

0 commit comments

Comments
 (0)
0