]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Differentiate the two dependencies
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Mon, 27 Oct 2025 10:44:10 +0000 (10:44 +0000)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Mon, 27 Oct 2025 10:44:10 +0000 (10:44 +0000)
Python/optimizer.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index f745f16fcf30b7fc39f8e68bf167d295d644bf9b..da9247cd139ca4c567edc4d7121deed1fa00e9ba 100644 (file)
@@ -860,6 +860,7 @@ _PyJit_translate_single_bytecode_to_trace(
                 if (uop == _PUSH_FRAME || uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) {
                     PyCodeObject *new_code = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable);
                     PyFunctionObject *new_func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+
                     if (new_func != NULL) {
                         operand = (uintptr_t)new_func;
                         DPRINTF(2, "Adding %p func to op\n", (void *)operand);
@@ -1277,7 +1278,17 @@ uop_optimize(
     _PyExecutorObject **exec_ptr,
     bool progress_needed)
 {
-    _PyBloomFilter *dependencies = &tstate->interp->jit_state.dependencies;
+    // Note: the executor has a slightly different set of dependencies than the tracer.
+    // For example: the tracer depends on function and code objects.
+    // The executor may only depend on the code object.
+    // Furthermore, it may decide to cut the trace early, meaning it does not depend on the rest
+    // of the code objects in the trace.
+    // It is crucial we differentiate them for performance reasons.
+    // This prevents endless re-tracing for nested functions.
+    // It is the optimizer's responsibility to add the dependencies it requires on its own.
+    _PyBloomFilter new_dependencies;
+    _Py_BloomFilter_Init(&new_dependencies);
+    _Py_BloomFilter_Add(&new_dependencies, tstate->interp->jit_state.initial_code);
     PyInterpreterState *interp = _PyInterpreterState_GET();
     _PyUOpInstruction *buffer = interp->jit_state.code_buffer;
     OPT_STAT_INC(attempts);
@@ -1298,7 +1309,7 @@ uop_optimize(
     if (!is_noopt) {
         length = _Py_uop_analyze_and_optimize(tstate->interp->jit_state.initial_func, buffer,
                                            length,
-                                           curr_stackentries, dependencies);
+                                           curr_stackentries, &new_dependencies);
         if (length <= 0) {
             return length;
         }
@@ -1321,7 +1332,7 @@ uop_optimize(
     OPT_HIST(effective_trace_length(buffer, length), optimized_trace_length_hist);
     length = prepare_for_execution(buffer, length);
     assert(length <= UOP_MAX_TRACE_LENGTH);
-    _PyExecutorObject *executor = make_executor_from_uops(buffer, length,  dependencies, tstate->interp->jit_state.initial_chain_depth);
+    _PyExecutorObject *executor = make_executor_from_uops(buffer, length, &new_dependencies, tstate->interp->jit_state.initial_chain_depth);
     if (executor == NULL) {
         return -1;
     }
index 7e4a9778a89efe8ac548722da7ea9cf327bfa141..d57bea14c5ad76a7cc483be76f5b8df5e68e4505 100644 (file)
@@ -779,6 +779,7 @@ dummy_func(void) {
             ctx->done = true;
             break;
         }
+        _Py_BloomFilter_Add(dependencies, returning_code);
         int returning_stacklevel = this_instr->operand1;
         if (frame_pop(ctx, returning_code, returning_stacklevel)) {
             break;
@@ -797,6 +798,7 @@ dummy_func(void) {
             ctx->done = true;
             break;
         }
+        _Py_BloomFilter_Add(dependencies, returning_code);
         int returning_stacklevel = this_instr->operand1;
         if (frame_pop(ctx, returning_code, returning_stacklevel)) {
             break;
@@ -815,6 +817,7 @@ dummy_func(void) {
             ctx->done = true;
             break;
         }
+        _Py_BloomFilter_Add(dependencies, returning_code);
         int returning_stacklevel = this_instr->operand1;
         if (frame_pop(ctx, returning_code, returning_stacklevel)) {
             break;
@@ -871,6 +874,7 @@ dummy_func(void) {
         }
         PyFunctionObject *func = (PyFunctionObject *)operand;
         PyCodeObject *co = (PyCodeObject *)func->func_code;
+        _Py_BloomFilter_Add(dependencies, co);
         assert(PyFunction_Check(func));
         ctx->frame->func = func;
     }
index 5192280e5ca20f5270b8c5ff40e67e022fca9ac7..5f7d600b3cd2a91d367fc14c48ce8c51378e2856 100644 (file)
                 ctx->done = true;
                 break;
             }
+            _Py_BloomFilter_Add(dependencies, returning_code);
             int returning_stacklevel = this_instr->operand1;
             if (frame_pop(ctx, returning_code, returning_stacklevel)) {
                 break;
                 ctx->done = true;
                 break;
             }
+            _Py_BloomFilter_Add(dependencies, returning_code);
             int returning_stacklevel = this_instr->operand1;
             if (frame_pop(ctx, returning_code, returning_stacklevel)) {
                 break;
             }
             PyFunctionObject *func = (PyFunctionObject *)operand;
             PyCodeObject *co = (PyCodeObject *)func->func_code;
+            _Py_BloomFilter_Add(dependencies, co);
             assert(PyFunction_Check(func));
             ctx->frame->func = func;
             break;
                 ctx->done = true;
                 break;
             }
+            _Py_BloomFilter_Add(dependencies, returning_code);
             int returning_stacklevel = this_instr->operand1;
             if (frame_pop(ctx, returning_code, returning_stacklevel)) {
                 break;