Skip to content

Commit 7d4f866

Browse files
invalidate freed code/function objects used for global promotion
1 parent c0c14b4 commit 7d4f866

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

Include/internal/pycore_interp_structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,7 @@ struct _is {
947947
int jit_tracer_code_max_size;
948948
int jit_tracer_code_curr_size;
949949
_PyBloomFilter jit_tracer_dependencies;
950+
bool jit_tracer_dependencies_still_valid;
950951
_PyUOpInstruction *jit_tracer_code_buffer;
951952
_Py_CODEUNIT *jit_tracer_initial_instr;
952953
int jit_tracer_initial_stack_depth;

Include/internal/pycore_optimizer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,9 @@ void
375375
_PyJIT_InitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit);
376376

377377
void _PyJIT_FinalizeTracing(PyThreadState *tstate);
378+
379+
void _Py_JITTracer_InvalidateDependency(PyThreadState *old_tstate, void *obj);
380+
378381
#ifdef __cplusplus
379382
}
380383
#endif

Objects/codeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,6 +2415,7 @@ code_dealloc(PyObject *self)
24152415
PyMem_Free(co_extra);
24162416
}
24172417
#ifdef _Py_TIER2
2418+
_Py_JITTracer_InvalidateDependency(tstate, self);
24182419
if (co->co_executors != NULL) {
24192420
clear_executors(co);
24202421
}

Objects/funcobject.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "pycore_setobject.h" // _PySet_NextEntry()
1212
#include "pycore_stats.h"
1313
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
14-
14+
#include "pycore_optimizer.h" // _Py_JITTracer_InvalidateDependency
1515

1616
static const char *
1717
func_event_name(PyFunction_WatchEvent event) {
@@ -1149,6 +1149,9 @@ func_dealloc(PyObject *self)
11491149
if (_PyObject_ResurrectEnd(self)) {
11501150
return;
11511151
}
1152+
#if _Py_TIER2
1153+
_Py_JITTracer_InvalidateDependency(PyThreadState_GET(), self);
1154+
#endif
11521155
_PyObject_GC_UNTRACK(op);
11531156
FT_CLEAR_WEAKREFS(self, op->func_weakreflist);
11541157
(void)func_clear((PyObject*)op);

Python/optimizer.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ _PyOptimizer_Optimize(
147147
interp->compiling = false;
148148
return 0;
149149
}
150+
// One of our depencies while tracing was invalidated. Not worth compiling.
151+
if (!tstate->interp->jit_tracer_dependencies_still_valid) {
152+
interp->compiling = false;
153+
return 0;
154+
}
150155
_PyExecutorObject *executor;
151156
int err = uop_optimize(frame, tstate, &executor, progress_needed);
152157
if (err <= 0) {
@@ -560,9 +565,6 @@ _PyJIT_translate_single_bytecode_to_trace(
560565
int oparg,
561566
int jump_taken)
562567
{
563-
if (PyStackRef_IsNull(frame->f_funcobj)) {
564-
goto unsupported;
565-
}
566568

567569
int is_first_instr = tstate->interp->jit_tracer_initial_instr == this_instr;
568570
bool progress_needed = (tstate->interp->jit_tracer_initial_chain_depth % MAX_CHAIN_DEPTH) == 0 && is_first_instr;;
@@ -794,12 +796,16 @@ _PyJIT_translate_single_bytecode_to_trace(
794796
}
795797
if (uop == _PUSH_FRAME || uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) {
796798
PyCodeObject *new_code = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable);
797-
PyFunctionObject *new_func = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
799+
PyFunctionObject *new_func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
798800
if (new_func != NULL) {
799801
operand = (uintptr_t)new_func;
802+
DPRINTF(2, "Adding %p func to op\n", (void *)operand);
803+
_Py_BloomFilter_Add(dependencies, new_func);
800804
}
801805
else if (new_code != NULL) {
802806
operand = (uintptr_t)new_code | 1;
807+
DPRINTF(2, "Adding %p code to op\n", (void *)operand);
808+
_Py_BloomFilter_Add(dependencies, new_code);
803809
}
804810
else {
805811
operand = 0;
@@ -866,6 +872,7 @@ _PyJIT_InitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_
866872
tstate->interp->jit_tracer_initial_stack_depth = curr_stackdepth;
867873
tstate->interp->jit_tracer_initial_chain_depth = chain_depth;
868874
tstate->interp->jit_tracer_current_frame = frame;
875+
tstate->interp->jit_tracer_dependencies_still_valid = true;
869876
}
870877

871878
void
@@ -1530,6 +1537,25 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
15301537
_Py_Executors_InvalidateAll(interp, is_invalidation);
15311538
}
15321539

1540+
void
1541+
_Py_JITTracer_InvalidateDependency(PyThreadState *old_tstate, void *obj)
1542+
{
1543+
_PyBloomFilter obj_filter;
1544+
_Py_BloomFilter_Init(&obj_filter);
1545+
_Py_BloomFilter_Add(&obj_filter, obj);
1546+
HEAD_LOCK(&_PyRuntime);
1547+
1548+
PyInterpreterState *interp = old_tstate->interp;
1549+
1550+
_Py_FOR_EACH_TSTATE_UNLOCKED(interp, tstate) {
1551+
if (bloom_filter_may_contain(&tstate->interp->jit_tracer_dependencies, &obj_filter))
1552+
{
1553+
tstate->interp->jit_tracer_dependencies_still_valid = false;
1554+
}
1555+
1556+
}
1557+
HEAD_UNLOCK(&_PyRuntime);
1558+
}
15331559
/* Invalidate all executors */
15341560
void
15351561
_Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)

0 commit comments

Comments
 (0)