gh-137838: Move _PyUOpInstruction buffer to PyInterpreterState (gh-138918)

This commit is contained in:
Donghee Na
2025-09-17 18:50:16 +01:00
committed by GitHub
parent a9b6b09141
commit d873fb42f3
8 changed files with 87 additions and 31 deletions

View File

@@ -116,7 +116,10 @@ _PyOptimizer_Optimize(
_PyExecutorObject **executor_ptr, int chain_depth)
{
_PyStackRef *stack_pointer = frame->stackpointer;
assert(_PyInterpreterState_GET()->jit);
PyInterpreterState *interp = _PyInterpreterState_GET();
assert(interp->jit);
assert(!interp->compiling);
interp->compiling = true;
// The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must*
// make progress in order to avoid infinite loops or excessively-long
// side-exit chains. We can only insert the executor into the bytecode if
@@ -126,10 +129,12 @@ _PyOptimizer_Optimize(
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(PyCode_Check(code));
if (progress_needed && !has_space_for_executor(code, start)) {
interp->compiling = false;
return 0;
}
int err = uop_optimize(frame, start, executor_ptr, (int)(stack_pointer - _PyFrame_Stackbase(frame)), progress_needed);
if (err <= 0) {
interp->compiling = false;
return err;
}
assert(*executor_ptr != NULL);
@@ -143,6 +148,7 @@ _PyOptimizer_Optimize(
* it might get confused by the executor disappearing,
* but there is not much we can do about that here. */
Py_DECREF(*executor_ptr);
interp->compiling = false;
return 0;
}
insert_executor(code, start, index, *executor_ptr);
@@ -152,6 +158,7 @@ _PyOptimizer_Optimize(
}
(*executor_ptr)->vm_data.chain_depth = chain_depth;
assert((*executor_ptr)->vm_data.valid);
interp->compiling = false;
return 1;
}
@@ -1280,7 +1287,14 @@ uop_optimize(
{
_PyBloomFilter dependencies;
_Py_BloomFilter_Init(&dependencies);
_PyUOpInstruction buffer[UOP_MAX_TRACE_LENGTH];
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->jit_uop_buffer == NULL) {
interp->jit_uop_buffer = (_PyUOpInstruction *)_PyObject_VirtualAlloc(UOP_BUFFER_SIZE);
if (interp->jit_uop_buffer == NULL) {
return 0;
}
}
_PyUOpInstruction *buffer = interp->jit_uop_buffer;
OPT_STAT_INC(attempts);
char *env_var = Py_GETENV("PYTHON_UOPS_OPTIMIZE");
bool is_noopt = true;

View File

@@ -1702,6 +1702,7 @@ finalize_modules(PyThreadState *tstate)
// Invalidate all executors and turn off JIT:
interp->jit = false;
interp->compiling = false;
#ifdef _Py_TIER2
_Py_Executors_InvalidateAll(interp, 0);
#endif

View File

@@ -22,6 +22,7 @@
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
#include "pycore_stackref.h" // Py_STACKREF_DEBUG
#include "pycore_time.h" // _PyTime_Init()
#include "pycore_uop.h" // UOP_BUFFER_SIZE
#include "pycore_uniqueid.h" // _PyObject_FinalizePerThreadRefcounts()
@@ -550,6 +551,11 @@ init_interpreter(PyInterpreterState *interp,
#ifdef Py_GIL_DISABLED
_Py_brc_init_state(interp);
#endif
#ifdef _Py_TIER2
// Ensure the buffer is to be set as NULL.
interp->jit_uop_buffer = NULL;
#endif
llist_init(&interp->mem_free_queue.head);
llist_init(&interp->asyncio_tasks_head);
interp->asyncio_tasks_lock = (PyMutex){0};
@@ -565,6 +571,7 @@ init_interpreter(PyInterpreterState *interp,
}
interp->_code_object_generation = 0;
interp->jit = false;
interp->compiling = false;
interp->executor_list_head = NULL;
interp->executor_deletion_list_head = NULL;
interp->executor_deletion_list_remaining_capacity = 0;
@@ -797,6 +804,10 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
#ifdef _Py_TIER2
_Py_ClearExecutorDeletionList(interp);
if (interp->jit_uop_buffer != NULL) {
_PyObject_VirtualFree(interp->jit_uop_buffer, UOP_BUFFER_SIZE);
interp->jit_uop_buffer = NULL;
}
#endif
_PyAST_Fini(interp);
_PyAtExit_Fini(interp);