]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Change the backoffs to fix nqueens
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Sat, 25 Oct 2025 23:56:37 +0000 (00:56 +0100)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Sat, 25 Oct 2025 23:56:37 +0000 (00:56 +0100)
Include/internal/pycore_backoff.h
Python/optimizer.c

index f92dfd278a1e6867daae4b2d7f9efbd9a94d9dae..86ae7885fd1c5e90d05d8a97e20a782253cd0685 100644 (file)
@@ -99,8 +99,13 @@ backoff_counter_triggers(_Py_BackoffCounter counter)
 // Must be larger than ADAPTIVE_COOLDOWN_VALUE, otherwise when JIT code is
 // invalidated we may construct a new trace before the bytecode has properly
 // re-specialized:
-#define JUMP_BACKWARD_INITIAL_VALUE 4095
-#define JUMP_BACKWARD_INITIAL_BACKOFF 12
+// Note: this should be a prime number-1. This increases the likelihood of
+// finding a "good" loop iteration to trace.
+// For example, 4095 does not work for the nqueens benchmark on pyperformanc
+// as we always end up tracing the loop iteration's
+// exhaustion iteration. Which aborts our current tracer.
+#define JUMP_BACKWARD_INITIAL_VALUE 4000
+#define JUMP_BACKWARD_INITIAL_BACKOFF 14
 static inline _Py_BackoffCounter
 initial_jump_backoff_counter(void)
 {
@@ -112,7 +117,7 @@ initial_jump_backoff_counter(void)
  * Must be larger than ADAPTIVE_COOLDOWN_VALUE,
  * otherwise when a side exit warms up we may construct
  * a new trace before the Tier 1 code has properly re-specialized. */
-#define SIDE_EXIT_INITIAL_VALUE 4095
+#define SIDE_EXIT_INITIAL_VALUE 4000
 #define SIDE_EXIT_INITIAL_BACKOFF 12
 
 static inline _Py_BackoffCounter
index d39156a41afdc2d502130c03b5ad46ba3b5a7d1c..995ddee8605878c63653a254c118f33b20d08b8f 100644 (file)
@@ -628,16 +628,19 @@ _PyJit_translate_single_bytecode_to_trace(
 
     // Strange control-flow, unsupported opcode, etc.
     if (tstate->interp->jit_state.dynamic_jump_taken) {
+        DPRINTF(2, "Unsupported: dynamic jump taken\n");
         goto unsupported;
     }
 
     // This happens when a recursive call happens that we can't trace. Such as Python -> C -> Python calls
     // If we haven't guarded the IP, then it's untraceable.
     if (frame != tstate->interp->jit_state.prev_instr_frame && !needs_guard_ip) {
+        DPRINTF(2, "Unsupported: unguardable jump taken\n");
         goto unsupported;
     }
 
     if (oparg > 0xFFFF) {
+        DPRINTF(2, "Unsupported: oparg too large\n");
         goto unsupported;
     }
 
@@ -647,10 +650,12 @@ _PyJit_translate_single_bytecode_to_trace(
     }
 
     if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW || opcode == PUSH_EXC_INFO) {
+        DPRINTF(2, "Unsupported: strange control-flow\n");
         goto unsupported;
     }
 
     if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
+        DPRINTF(2, "Unsupported: frame owned by interpreter\n");
         unsupported:
         {
             // Rewind to previous instruction and replace with _EXIT_TRACE.