https://github.com/python/cpython/commit/a269e691de91fcc0982701839ebaf68978753172
commit: a269e691de91fcc0982701839ebaf68978753172
branch: main
author: Ken Jin <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2025-09-18T14:12:07+01:00
summary:
gh-139109: Dynamic opcode targets (GH-139111)
Make opcode targets table dynamic
files:
M Python/ceval.c
M Python/ceval_macros.h
M Python/opcode_targets.h
M Tools/c-analyzer/cpython/_parser.py
M Tools/cases_generator/target_generator.py
diff --git a/Python/ceval.c b/Python/ceval.c
index a532f17a97f7a8..7abbc9e9fd12b6 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1022,6 +1022,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate,
_PyInterpreterFrame *frame, int
#if USE_COMPUTED_GOTOS && !_Py_TAIL_CALL_INTERP
/* Import the static jump table */
#include "opcode_targets.h"
+ void **opcode_targets = opcode_targets_table;
#endif
#ifdef Py_STATS
@@ -1101,9 +1102,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate,
_PyInterpreterFrame *frame, int
stack_pointer = _PyFrame_GetStackPointer(frame);
#if _Py_TAIL_CALL_INTERP
# if Py_STATS
- return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 0,
lastopcode);
+ return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr,
instruction_funcptr_table, 0, lastopcode);
# else
- return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 0);
+ return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr,
instruction_funcptr_table, 0);
# endif
#else
goto error;
@@ -1112,9 +1113,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate,
_PyInterpreterFrame *frame, int
#if _Py_TAIL_CALL_INTERP
# if Py_STATS
- return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0,
lastopcode);
+ return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL,
instruction_funcptr_table, 0, lastopcode);
# else
- return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0);
+ return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL,
instruction_funcptr_table, 0);
# endif
#else
goto start_frame;
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index 7799fd11203e71..4ed03b7fb01bdf 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -71,11 +71,11 @@
#endif
#ifdef Py_STATS
-# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg, int
lastopcode
-# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg,
lastopcode
+# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, const void
*instruction_funcptr_table, int oparg, int lastopcode
+# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr,
instruction_funcptr_table, oparg, lastopcode
#else
-# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg
-# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg
+# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, const void
*instruction_funcptr_table, int oparg
+# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr,
instruction_funcptr_table, oparg
#endif
#if _Py_TAIL_CALL_INTERP
@@ -87,7 +87,7 @@
# define TARGET(op) Py_PRESERVE_NONE_CC PyObject
*_TAIL_CALL_##op(TAIL_CALL_PARAMS)
# define DISPATCH_GOTO() \
do { \
- Py_MUSTTAIL return (INSTRUCTION_TABLE[opcode])(TAIL_CALL_ARGS); \
+ Py_MUSTTAIL return (((py_tail_call_funcptr
*)instruction_funcptr_table)[opcode])(TAIL_CALL_ARGS); \
} while (0)
# define JUMP_TO_LABEL(name) \
do { \
@@ -96,12 +96,12 @@
# ifdef Py_STATS
# define JUMP_TO_PREDICTED(name) \
do { \
- Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer,
tstate, this_instr, oparg, lastopcode); \
+ Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer,
tstate, this_instr, instruction_funcptr_table, oparg, lastopcode); \
} while (0)
# else
# define JUMP_TO_PREDICTED(name) \
do { \
- Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer,
tstate, this_instr, oparg); \
+ Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer,
tstate, this_instr, instruction_funcptr_table, oparg); \
} while (0)
# endif
# define LABEL(name) TARGET(name)
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 33607b2115f5d0..6dd443e1655ed0 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -1,5 +1,5 @@
#if !_Py_TAIL_CALL_INTERP
-static void *opcode_targets[256] = {
+static void *opcode_targets_table[256] = {
&&TARGET_CACHE,
&&TARGET_BINARY_SLICE,
&&TARGET_BUILD_TEMPLATE,
@@ -258,7 +258,7 @@ static void *opcode_targets[256] = {
&&TARGET_ENTER_EXECUTOR,
};
#else /* _Py_TAIL_CALL_INTERP */
-static py_tail_call_funcptr INSTRUCTION_TABLE[256];
+static py_tail_call_funcptr instruction_funcptr_table[256];
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_2_error(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_1_error(TAIL_CALL_PARAMS);
@@ -503,7 +503,7 @@ Py_PRESERVE_NONE_CC static PyObject
*_TAIL_CALL_UNKNOWN_OPCODE(TAIL_CALL_PARAMS)
JUMP_TO_LABEL(error);
}
-static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {
+static py_tail_call_funcptr instruction_funcptr_table[256] = {
[BINARY_OP] = _TAIL_CALL_BINARY_OP,
[BINARY_OP_ADD_FLOAT] = _TAIL_CALL_BINARY_OP_ADD_FLOAT,
[BINARY_OP_ADD_INT] = _TAIL_CALL_BINARY_OP_ADD_INT,
diff --git a/Tools/c-analyzer/cpython/_parser.py
b/Tools/c-analyzer/cpython/_parser.py
index bd30809b0fba43..17c56c9e8762c6 100644
--- a/Tools/c-analyzer/cpython/_parser.py
+++ b/Tools/c-analyzer/cpython/_parser.py
@@ -80,6 +80,7 @@ def format_tsv_lines(lines):
'Python/generated_cases.c.h',
'Python/executor_cases.c.h',
'Python/optimizer_cases.c.h',
+ 'Python/opcode_targets.h',
# XXX: Throws errors if PY_VERSION_HEX is not mocked out
'Modules/clinic/_testclinic_depr.c.h',
diff --git a/Tools/cases_generator/target_generator.py
b/Tools/cases_generator/target_generator.py
index 1a1a014837e259..324ef2773abe28 100644
--- a/Tools/cases_generator/target_generator.py
+++ b/Tools/cases_generator/target_generator.py
@@ -27,7 +27,7 @@ def write_opcode_targets(analysis: Analysis, out: CWriter) ->
None:
if op < 256:
targets[op] = f"&&TARGET_{name},\n"
out.emit("#if !_Py_TAIL_CALL_INTERP\n")
- out.emit("static void *opcode_targets[256] = {\n")
+ out.emit("static void *opcode_targets_table[256] = {\n")
for target in targets:
out.emit(target)
out.emit("};\n")
@@ -38,7 +38,7 @@ def function_proto(name: str) -> str:
def write_tailcall_dispatch_table(analysis: Analysis, out: CWriter) -> None:
- out.emit("static py_tail_call_funcptr INSTRUCTION_TABLE[256];\n")
+ out.emit("static py_tail_call_funcptr instruction_funcptr_table[256];\n")
out.emit("\n")
# Emit function prototypes for labels.
@@ -60,7 +60,7 @@ def write_tailcall_dispatch_table(analysis: Analysis, out:
CWriter) -> None:
out.emit("\n")
# Emit the dispatch table.
- out.emit("static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {\n")
+ out.emit("static py_tail_call_funcptr instruction_funcptr_table[256] =
{\n")
for name in sorted(analysis.instructions.keys()):
out.emit(f"[{name}] = _TAIL_CALL_{name},\n")
named_values = analysis.opmap.values()
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]