mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
gh-104584: Move super-instruction special-casing to generator (#106500)
Instead of special-casing specific instructions, we add a few more special values to the 'size' field of expansions, so in the future we can automatically handle additional super-instructions in the generator.
This commit is contained in:
parent
363f4f99c5
commit
11038c56ad
3 changed files with 84 additions and 39 deletions
9
Python/opcode_metadata.h
generated
9
Python/opcode_metadata.h
generated
|
@ -934,6 +934,12 @@ struct opcode_macro_expansion {
|
|||
struct { int16_t uop; int8_t size; int8_t offset; } uops[8];
|
||||
};
|
||||
|
||||
#define OPARG_FULL 0
|
||||
#define OPARG_CACHE_1 1
|
||||
#define OPARG_CACHE_2 2
|
||||
#define OPARG_CACHE_4 4
|
||||
#define OPARG_TOP 5
|
||||
#define OPARG_BOTTOM 6
|
||||
|
||||
#define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format)
|
||||
#define SAME_OPCODE_METADATA(OP1, OP2) \
|
||||
|
@ -1165,8 +1171,11 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] = {
|
|||
[LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { LOAD_FAST_CHECK, 0, 0 } } },
|
||||
[LOAD_FAST] = { .nuops = 1, .uops = { { LOAD_FAST, 0, 0 } } },
|
||||
[LOAD_FAST_AND_CLEAR] = { .nuops = 1, .uops = { { LOAD_FAST_AND_CLEAR, 0, 0 } } },
|
||||
[LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { LOAD_FAST, 5, 0 }, { LOAD_FAST, 6, 0 } } },
|
||||
[LOAD_CONST] = { .nuops = 1, .uops = { { LOAD_CONST, 0, 0 } } },
|
||||
[STORE_FAST] = { .nuops = 1, .uops = { { STORE_FAST, 0, 0 } } },
|
||||
[STORE_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { STORE_FAST, 5, 0 }, { LOAD_FAST, 6, 0 } } },
|
||||
[STORE_FAST_STORE_FAST] = { .nuops = 2, .uops = { { STORE_FAST, 5, 0 }, { STORE_FAST, 6, 0 } } },
|
||||
[POP_TOP] = { .nuops = 1, .uops = { { POP_TOP, 0, 0 } } },
|
||||
[PUSH_NULL] = { .nuops = 1, .uops = { { PUSH_NULL, 0, 0 } } },
|
||||
[END_FOR] = { .nuops = 2, .uops = { { POP_TOP, 0, 0 }, { POP_TOP, 0, 0 } } },
|
||||
|
|
|
@ -411,44 +411,15 @@ translate_bytecode_to_trace(
|
|||
for (;;) {
|
||||
ADD_TO_TRACE(SAVE_IP, (int)(instr - (_Py_CODEUNIT *)code->co_code_adaptive));
|
||||
int opcode = instr->op.code;
|
||||
uint64_t operand = instr->op.arg;
|
||||
int oparg = instr->op.arg;
|
||||
int extras = 0;
|
||||
while (opcode == EXTENDED_ARG) {
|
||||
instr++;
|
||||
extras += 1;
|
||||
opcode = instr->op.code;
|
||||
operand = (operand << 8) | instr->op.arg;
|
||||
oparg = (oparg << 8) | instr->op.arg;
|
||||
}
|
||||
switch (opcode) {
|
||||
case LOAD_FAST_LOAD_FAST:
|
||||
case STORE_FAST_LOAD_FAST:
|
||||
case STORE_FAST_STORE_FAST:
|
||||
{
|
||||
// Reserve space for two uops (+ SAVE_IP + EXIT_TRACE)
|
||||
if (trace_length + 4 > max_length) {
|
||||
DPRINTF(1, "Ran out of space for LOAD_FAST_LOAD_FAST\n");
|
||||
goto done;
|
||||
}
|
||||
uint64_t oparg1 = operand >> 4;
|
||||
uint64_t oparg2 = operand & 15;
|
||||
switch (opcode) {
|
||||
case LOAD_FAST_LOAD_FAST:
|
||||
ADD_TO_TRACE(LOAD_FAST, oparg1);
|
||||
ADD_TO_TRACE(LOAD_FAST, oparg2);
|
||||
break;
|
||||
case STORE_FAST_LOAD_FAST:
|
||||
ADD_TO_TRACE(STORE_FAST, oparg1);
|
||||
ADD_TO_TRACE(LOAD_FAST, oparg2);
|
||||
break;
|
||||
case STORE_FAST_STORE_FAST:
|
||||
ADD_TO_TRACE(STORE_FAST, oparg1);
|
||||
ADD_TO_TRACE(STORE_FAST, oparg2);
|
||||
break;
|
||||
default:
|
||||
Py_FatalError("Missing case");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
|
||||
|
@ -462,9 +433,11 @@ translate_bytecode_to_trace(
|
|||
goto done;
|
||||
}
|
||||
for (int i = 0; i < nuops; i++) {
|
||||
uint64_t operand;
|
||||
int offset = expansion->uops[i].offset;
|
||||
switch (expansion->uops[i].size) {
|
||||
case 0:
|
||||
case OPARG_FULL:
|
||||
operand = oparg;
|
||||
if (extras && OPCODE_HAS_JUMP(opcode)) {
|
||||
if (opcode == JUMP_BACKWARD_NO_INTERRUPT) {
|
||||
operand -= extras;
|
||||
|
@ -475,19 +448,25 @@ translate_bytecode_to_trace(
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case OPARG_CACHE_1:
|
||||
operand = read_u16(&instr[offset].cache);
|
||||
break;
|
||||
case 2:
|
||||
case OPARG_CACHE_2:
|
||||
operand = read_u32(&instr[offset].cache);
|
||||
break;
|
||||
case 4:
|
||||
case OPARG_CACHE_4:
|
||||
operand = read_u64(&instr[offset].cache);
|
||||
break;
|
||||
case OPARG_TOP: // First half of super-instr
|
||||
operand = oparg >> 4;
|
||||
break;
|
||||
case OPARG_BOTTOM: // Second half of super-instr
|
||||
operand = oparg & 0xF;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"opcode=%d, operand=%" PRIu64 "; nuops=%d, i=%d; size=%d, offset=%d\n",
|
||||
opcode, operand, nuops, i,
|
||||
"opcode=%d, oparg=%d; nuops=%d, i=%d; size=%d, offset=%d\n",
|
||||
opcode, oparg, nuops, i,
|
||||
expansion->uops[i].size,
|
||||
expansion->uops[i].offset);
|
||||
Py_FatalError("garbled expansion");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue