mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-106701: Move the hand-written Tier 2 uops to bytecodes.c (#106702)
This moves EXIT_TRACE, SAVE_IP, JUMP_TO_TOP, and _POP_JUMP_IF_{FALSE,TRUE} from ceval.c to bytecodes.c. They are no less special than before, but this way they are discoverable o the copy-and-patch tooling.
This commit is contained in:
parent
2f3ee02c22
commit
e6e0ea0113
5 changed files with 124 additions and 94 deletions
100
Include/internal/pycore_opcode_metadata.h
generated
100
Include/internal/pycore_opcode_metadata.h
generated
|
@ -21,30 +21,30 @@
|
||||||
|
|
||||||
#define EXIT_TRACE 300
|
#define EXIT_TRACE 300
|
||||||
#define SAVE_IP 301
|
#define SAVE_IP 301
|
||||||
#define _POP_JUMP_IF_FALSE 302
|
#define _GUARD_BOTH_INT 302
|
||||||
#define _POP_JUMP_IF_TRUE 303
|
#define _BINARY_OP_MULTIPLY_INT 303
|
||||||
#define JUMP_TO_TOP 304
|
#define _BINARY_OP_ADD_INT 304
|
||||||
#define _GUARD_BOTH_INT 305
|
#define _BINARY_OP_SUBTRACT_INT 305
|
||||||
#define _BINARY_OP_MULTIPLY_INT 306
|
#define _GUARD_BOTH_FLOAT 306
|
||||||
#define _BINARY_OP_ADD_INT 307
|
#define _BINARY_OP_MULTIPLY_FLOAT 307
|
||||||
#define _BINARY_OP_SUBTRACT_INT 308
|
#define _BINARY_OP_ADD_FLOAT 308
|
||||||
#define _GUARD_BOTH_FLOAT 309
|
#define _BINARY_OP_SUBTRACT_FLOAT 309
|
||||||
#define _BINARY_OP_MULTIPLY_FLOAT 310
|
#define _GUARD_BOTH_UNICODE 310
|
||||||
#define _BINARY_OP_ADD_FLOAT 311
|
#define _BINARY_OP_ADD_UNICODE 311
|
||||||
#define _BINARY_OP_SUBTRACT_FLOAT 312
|
#define _LOAD_LOCALS 312
|
||||||
#define _GUARD_BOTH_UNICODE 313
|
#define _LOAD_FROM_DICT_OR_GLOBALS 313
|
||||||
#define _BINARY_OP_ADD_UNICODE 314
|
#define _SKIP_CACHE 314
|
||||||
#define _LOAD_LOCALS 315
|
#define _GUARD_GLOBALS_VERSION 315
|
||||||
#define _LOAD_FROM_DICT_OR_GLOBALS 316
|
#define _GUARD_BUILTINS_VERSION 316
|
||||||
#define _SKIP_CACHE 317
|
#define _GUARD_TYPE_VERSION 317
|
||||||
#define _GUARD_GLOBALS_VERSION 318
|
#define _CHECK_MANAGED_OBJECT_HAS_VALUES 318
|
||||||
#define _GUARD_BUILTINS_VERSION 319
|
#define IS_NONE 319
|
||||||
#define _GUARD_TYPE_VERSION 320
|
#define _ITER_CHECK_RANGE 320
|
||||||
#define _CHECK_MANAGED_OBJECT_HAS_VALUES 321
|
#define _ITER_EXHAUSTED_RANGE 321
|
||||||
#define IS_NONE 322
|
#define _ITER_NEXT_RANGE 322
|
||||||
#define _ITER_CHECK_RANGE 323
|
#define _POP_JUMP_IF_FALSE 323
|
||||||
#define _ITER_EXHAUSTED_RANGE 324
|
#define _POP_JUMP_IF_TRUE 324
|
||||||
#define _ITER_NEXT_RANGE 325
|
#define JUMP_TO_TOP 325
|
||||||
|
|
||||||
#ifndef NEED_OPCODE_METADATA
|
#ifndef NEED_OPCODE_METADATA
|
||||||
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
||||||
|
@ -1303,31 +1303,31 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] = {
|
||||||
[SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } },
|
[SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } },
|
||||||
};
|
};
|
||||||
const char * const _PyOpcode_uop_name[512] = {
|
const char * const _PyOpcode_uop_name[512] = {
|
||||||
[300] = "EXIT_TRACE",
|
[EXIT_TRACE] = "EXIT_TRACE",
|
||||||
[301] = "SAVE_IP",
|
[SAVE_IP] = "SAVE_IP",
|
||||||
[302] = "_POP_JUMP_IF_FALSE",
|
[_GUARD_BOTH_INT] = "_GUARD_BOTH_INT",
|
||||||
[303] = "_POP_JUMP_IF_TRUE",
|
[_BINARY_OP_MULTIPLY_INT] = "_BINARY_OP_MULTIPLY_INT",
|
||||||
[304] = "JUMP_TO_TOP",
|
[_BINARY_OP_ADD_INT] = "_BINARY_OP_ADD_INT",
|
||||||
[305] = "_GUARD_BOTH_INT",
|
[_BINARY_OP_SUBTRACT_INT] = "_BINARY_OP_SUBTRACT_INT",
|
||||||
[306] = "_BINARY_OP_MULTIPLY_INT",
|
[_GUARD_BOTH_FLOAT] = "_GUARD_BOTH_FLOAT",
|
||||||
[307] = "_BINARY_OP_ADD_INT",
|
[_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT",
|
||||||
[308] = "_BINARY_OP_SUBTRACT_INT",
|
[_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT",
|
||||||
[309] = "_GUARD_BOTH_FLOAT",
|
[_BINARY_OP_SUBTRACT_FLOAT] = "_BINARY_OP_SUBTRACT_FLOAT",
|
||||||
[310] = "_BINARY_OP_MULTIPLY_FLOAT",
|
[_GUARD_BOTH_UNICODE] = "_GUARD_BOTH_UNICODE",
|
||||||
[311] = "_BINARY_OP_ADD_FLOAT",
|
[_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE",
|
||||||
[312] = "_BINARY_OP_SUBTRACT_FLOAT",
|
[_LOAD_LOCALS] = "_LOAD_LOCALS",
|
||||||
[313] = "_GUARD_BOTH_UNICODE",
|
[_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS",
|
||||||
[314] = "_BINARY_OP_ADD_UNICODE",
|
[_SKIP_CACHE] = "_SKIP_CACHE",
|
||||||
[315] = "_LOAD_LOCALS",
|
[_GUARD_GLOBALS_VERSION] = "_GUARD_GLOBALS_VERSION",
|
||||||
[316] = "_LOAD_FROM_DICT_OR_GLOBALS",
|
[_GUARD_BUILTINS_VERSION] = "_GUARD_BUILTINS_VERSION",
|
||||||
[317] = "_SKIP_CACHE",
|
[_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION",
|
||||||
[318] = "_GUARD_GLOBALS_VERSION",
|
[_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
|
||||||
[319] = "_GUARD_BUILTINS_VERSION",
|
[IS_NONE] = "IS_NONE",
|
||||||
[320] = "_GUARD_TYPE_VERSION",
|
[_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE",
|
||||||
[321] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
|
[_ITER_EXHAUSTED_RANGE] = "_ITER_EXHAUSTED_RANGE",
|
||||||
[322] = "IS_NONE",
|
[_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE",
|
||||||
[323] = "_ITER_CHECK_RANGE",
|
[_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
|
||||||
[324] = "_ITER_EXHAUSTED_RANGE",
|
[_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
|
||||||
[325] = "_ITER_NEXT_RANGE",
|
[JUMP_TO_TOP] = "JUMP_TO_TOP",
|
||||||
};
|
};
|
||||||
#endif // NEED_OPCODE_METADATA
|
#endif // NEED_OPCODE_METADATA
|
||||||
|
|
|
@ -3654,6 +3654,36 @@ dummy_func(
|
||||||
Py_UNREACHABLE();
|
Py_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////// Tier-2 only opcodes /////////
|
||||||
|
|
||||||
|
op(_POP_JUMP_IF_FALSE, (flag -- )) {
|
||||||
|
if (Py_IsFalse(flag)) {
|
||||||
|
pc = oparg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op(_POP_JUMP_IF_TRUE, (flag -- )) {
|
||||||
|
if (Py_IsTrue(flag)) {
|
||||||
|
pc = oparg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op(JUMP_TO_TOP, (--)) {
|
||||||
|
pc = 0;
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
op(SAVE_IP, (--)) {
|
||||||
|
frame->prev_instr = ip_offset + oparg;
|
||||||
|
}
|
||||||
|
|
||||||
|
op(EXIT_TRACE, (--)) {
|
||||||
|
frame->prev_instr--; // Back up to just before destination
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
Py_DECREF(self);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// END BYTECODES //
|
// END BYTECODES //
|
||||||
|
|
||||||
|
|
|
@ -2764,46 +2764,6 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
|
||||||
#define ENABLE_SPECIALIZATION 0
|
#define ENABLE_SPECIALIZATION 0
|
||||||
#include "executor_cases.c.h"
|
#include "executor_cases.c.h"
|
||||||
|
|
||||||
// NOTE: These pop-jumps move the uop pc, not the bytecode ip
|
|
||||||
case _POP_JUMP_IF_FALSE:
|
|
||||||
{
|
|
||||||
if (Py_IsFalse(stack_pointer[-1])) {
|
|
||||||
pc = oparg;
|
|
||||||
}
|
|
||||||
stack_pointer--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case _POP_JUMP_IF_TRUE:
|
|
||||||
{
|
|
||||||
if (Py_IsTrue(stack_pointer[-1])) {
|
|
||||||
pc = oparg;
|
|
||||||
}
|
|
||||||
stack_pointer--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case JUMP_TO_TOP:
|
|
||||||
{
|
|
||||||
pc = 0;
|
|
||||||
CHECK_EVAL_BREAKER();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SAVE_IP:
|
|
||||||
{
|
|
||||||
frame->prev_instr = ip_offset + oparg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EXIT_TRACE:
|
|
||||||
{
|
|
||||||
frame->prev_instr--; // Back up to just before destination
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
Py_DECREF(self);
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand);
|
fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand);
|
||||||
|
|
36
Python/executor_cases.c.h
generated
36
Python/executor_cases.c.h
generated
|
@ -1987,3 +1987,39 @@
|
||||||
stack_pointer[-(2 + (oparg-2))] = top;
|
stack_pointer[-(2 + (oparg-2))] = top;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _POP_JUMP_IF_FALSE: {
|
||||||
|
PyObject *flag = stack_pointer[-1];
|
||||||
|
if (Py_IsFalse(flag)) {
|
||||||
|
pc = oparg;
|
||||||
|
}
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _POP_JUMP_IF_TRUE: {
|
||||||
|
PyObject *flag = stack_pointer[-1];
|
||||||
|
if (Py_IsTrue(flag)) {
|
||||||
|
pc = oparg;
|
||||||
|
}
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JUMP_TO_TOP: {
|
||||||
|
pc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SAVE_IP: {
|
||||||
|
frame->prev_instr = ip_offset + oparg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EXIT_TRACE: {
|
||||||
|
frame->prev_instr--; // Back up to just before destination
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
Py_DECREF(self);
|
||||||
|
return frame;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
|
@ -410,6 +410,8 @@ class Instruction:
|
||||||
|
|
||||||
def is_viable_uop(self) -> bool:
|
def is_viable_uop(self) -> bool:
|
||||||
"""Whether this instruction is viable as a uop."""
|
"""Whether this instruction is viable as a uop."""
|
||||||
|
if self.name == "EXIT_TRACE":
|
||||||
|
return True # This has 'return frame' but it's okay
|
||||||
if self.always_exits:
|
if self.always_exits:
|
||||||
# print(f"Skipping {self.name} because it always exits")
|
# print(f"Skipping {self.name} because it always exits")
|
||||||
return False
|
return False
|
||||||
|
@ -1278,7 +1280,7 @@ class Analyzer:
|
||||||
typing.assert_never(thing)
|
typing.assert_never(thing)
|
||||||
|
|
||||||
with self.out.block("const char * const _PyOpcode_uop_name[512] =", ";"):
|
with self.out.block("const char * const _PyOpcode_uop_name[512] =", ";"):
|
||||||
self.write_uop_items(lambda name, counter: f"[{counter}] = \"{name}\",")
|
self.write_uop_items(lambda name, counter: f"[{name}] = \"{name}\",")
|
||||||
|
|
||||||
self.out.emit("#endif // NEED_OPCODE_METADATA")
|
self.out.emit("#endif // NEED_OPCODE_METADATA")
|
||||||
|
|
||||||
|
@ -1324,17 +1326,19 @@ class Analyzer:
|
||||||
def write_uop_items(self, make_text: typing.Callable[[str, int], str]) -> None:
|
def write_uop_items(self, make_text: typing.Callable[[str, int], str]) -> None:
|
||||||
"""Write '#define XXX NNN' for each uop"""
|
"""Write '#define XXX NNN' for each uop"""
|
||||||
counter = 300 # TODO: Avoid collision with pseudo instructions
|
counter = 300 # TODO: Avoid collision with pseudo instructions
|
||||||
|
seen = set()
|
||||||
|
|
||||||
def add(name: str) -> None:
|
def add(name: str) -> None:
|
||||||
|
if name in seen:
|
||||||
|
return
|
||||||
nonlocal counter
|
nonlocal counter
|
||||||
self.out.emit(make_text(name, counter))
|
self.out.emit(make_text(name, counter))
|
||||||
counter += 1
|
counter += 1
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
# These two are first by convention
|
||||||
add("EXIT_TRACE")
|
add("EXIT_TRACE")
|
||||||
add("SAVE_IP")
|
add("SAVE_IP")
|
||||||
add("_POP_JUMP_IF_FALSE")
|
|
||||||
add("_POP_JUMP_IF_TRUE")
|
|
||||||
add("JUMP_TO_TOP")
|
|
||||||
|
|
||||||
for instr in self.instrs.values():
|
for instr in self.instrs.values():
|
||||||
if instr.kind == "op" and instr.is_viable_uop():
|
if instr.kind == "op" and instr.is_viable_uop():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue