Skip to content

Commit 450e836

Browse files
authored
JIT: don't leak shim memory when shutting down the interpreter (#142984)
1 parent 20aeb3a commit 450e836

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

Include/internal/pycore_jit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef _Py_CODEUNIT *(*jit_func)(
2525

2626
int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length);
2727
void _PyJIT_Free(_PyExecutorObject *executor);
28+
void _PyJIT_Fini(void);
2829

2930
#endif // _Py_JIT
3031

Python/jit.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ typedef struct {
151151
uintptr_t instruction_starts[UOP_MAX_TRACE_LENGTH];
152152
} jit_state;
153153

154+
static size_t _Py_jit_shim_size = 0;
155+
154156
// Warning! AArch64 requires you to get your hands dirty. These are your gloves:
155157

156158
// value[value_start : value_start + len]
@@ -676,6 +678,7 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz
676678
* We compile this once only as it effectively a normal
677679
* function, but we need to use the JIT because it needs
678680
* to understand the jit-specific calling convention.
681+
* Don't forget to call _PyJIT_Fini later!
679682
*/
680683
static _PyJitEntryFuncPtr
681684
compile_shim(void)
@@ -717,6 +720,7 @@ compile_shim(void)
717720
jit_free(memory, total_size);
718721
return NULL;
719722
}
723+
_Py_jit_shim_size = total_size;
720724
return (_PyJitEntryFuncPtr)memory;
721725
}
722726

@@ -739,6 +743,7 @@ _Py_LazyJitShim(
739743
return _Py_jit_entry(executor, frame, stack_pointer, tstate);
740744
}
741745

746+
// Free executor's memory allocated with _PyJIT_Compile
742747
void
743748
_PyJIT_Free(_PyExecutorObject *executor)
744749
{
@@ -754,4 +759,22 @@ _PyJIT_Free(_PyExecutorObject *executor)
754759
}
755760
}
756761

762+
// Free shim memory allocated with compile_shim
763+
void
764+
_PyJIT_Fini(void)
765+
{
766+
PyMutex_Lock(&lazy_jit_mutex);
767+
unsigned char *memory = (unsigned char *)_Py_jit_entry;
768+
size_t size = _Py_jit_shim_size;
769+
if (size) {
770+
_Py_jit_entry = _Py_LazyJitShim;
771+
_Py_jit_shim_size = 0;
772+
if (jit_free(memory, size)) {
773+
PyErr_FormatUnraisable("Exception ignored while "
774+
"freeing JIT entry code");
775+
}
776+
}
777+
PyMutex_Unlock(&lazy_jit_mutex);
778+
}
779+
757780
#endif // _Py_JIT

Python/pylifecycle.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#include "pycore_uniqueid.h" // _PyObject_FinalizeUniqueIdPool()
3636
#include "pycore_warnings.h" // _PyWarnings_InitState()
3737
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
38+
#ifdef _Py_JIT
39+
#include "pycore_jit.h" // _PyJIT_Fini()
40+
#endif
3841

3942
#include "opcode.h"
4043

@@ -2267,6 +2270,7 @@ _Py_Finalize(_PyRuntimeState *runtime)
22672270
/* Print debug stats if any */
22682271
_PyEval_Fini();
22692272

2273+
22702274
/* Flush sys.stdout and sys.stderr (again, in case more was printed) */
22712275
if (flush_std_files() < 0) {
22722276
status = -1;
@@ -2346,6 +2350,10 @@ _Py_Finalize(_PyRuntimeState *runtime)
23462350

23472351
finalize_interp_clear(tstate);
23482352

2353+
#ifdef _Py_JIT
2354+
/* Free JIT shim memory */
2355+
_PyJIT_Fini();
2356+
#endif
23492357

23502358
#ifdef Py_TRACE_REFS
23512359
/* Display addresses (& refcnts) of all objects still alive.

0 commit comments

Comments
 (0)