mirror of
https://github.com/python/cpython.git
synced 2025-12-23 09:19:18 +00:00
GH-116422: Tier2 hot/cold splitting (GH-116813)
Splits the "cold" path, deopts and exits, from the "hot" path, reducing the size of most jitted instructions, at the cost of slower exits.
This commit is contained in:
parent
61599a48f5
commit
bf82f77957
21 changed files with 1662 additions and 1003 deletions
37
Python/jit.c
37
Python/jit.c
|
|
@ -381,11 +381,13 @@ int
|
|||
_PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length)
|
||||
{
|
||||
// Loop once to find the total compiled size:
|
||||
size_t code_size = 0;
|
||||
size_t data_size = 0;
|
||||
uint32_t instruction_starts[UOP_MAX_TRACE_LENGTH];
|
||||
uint32_t code_size = 0;
|
||||
uint32_t data_size = 0;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
_PyUOpInstruction *instruction = (_PyUOpInstruction *)&trace[i];
|
||||
const StencilGroup *group = &stencil_groups[instruction->opcode];
|
||||
instruction_starts[i] = code_size;
|
||||
code_size += group->code.body_size;
|
||||
data_size += group->data.body_size;
|
||||
}
|
||||
|
|
@ -403,11 +405,7 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size
|
|||
// Loop again to emit the code:
|
||||
unsigned char *code = memory;
|
||||
unsigned char *data = memory + code_size;
|
||||
unsigned char *top = code;
|
||||
if (trace[0].opcode == _START_EXECUTOR) {
|
||||
// Don't want to execute this more than once:
|
||||
top += stencil_groups[_START_EXECUTOR].code.body_size;
|
||||
}
|
||||
assert(trace[0].opcode == _START_EXECUTOR || trace[0].opcode == _COLD_EXIT);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
_PyUOpInstruction *instruction = (_PyUOpInstruction *)&trace[i];
|
||||
const StencilGroup *group = &stencil_groups[instruction->opcode];
|
||||
|
|
@ -419,8 +417,29 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size
|
|||
patches[HoleValue_EXECUTOR] = (uint64_t)executor;
|
||||
patches[HoleValue_OPARG] = instruction->oparg;
|
||||
patches[HoleValue_OPERAND] = instruction->operand;
|
||||
patches[HoleValue_TARGET] = instruction->target;
|
||||
patches[HoleValue_TOP] = (uint64_t)top;
|
||||
switch (instruction->format) {
|
||||
case UOP_FORMAT_TARGET:
|
||||
patches[HoleValue_TARGET] = instruction->target;
|
||||
break;
|
||||
case UOP_FORMAT_EXIT:
|
||||
assert(instruction->exit_index < executor->exit_count);
|
||||
patches[HoleValue_EXIT_INDEX] = instruction->exit_index;
|
||||
if (instruction->error_target < length) {
|
||||
patches[HoleValue_ERROR_TARGET] = (uint64_t)memory + instruction_starts[instruction->error_target];
|
||||
}
|
||||
break;
|
||||
case UOP_FORMAT_JUMP:
|
||||
assert(instruction->jump_target < length);
|
||||
patches[HoleValue_JUMP_TARGET] = (uint64_t)memory + instruction_starts[instruction->jump_target];
|
||||
if (instruction->error_target < length) {
|
||||
patches[HoleValue_ERROR_TARGET] = (uint64_t)memory + instruction_starts[instruction->error_target];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
Py_FatalError("Illegal instruction format");
|
||||
}
|
||||
patches[HoleValue_TOP] = (uint64_t)memory + instruction_starts[1];
|
||||
patches[HoleValue_ZERO] = 0;
|
||||
emit(group, patches);
|
||||
code += group->code.body_size;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue