Skip to content

JIT: Different behaviors when JIT is enabled. #144681

@nevercodecorrect

Description

@nevercodecorrect

Bug report

Bug description:

Below is the example I triggered. i am in commit 3dadc22a2796af7718f1aec02e30f100ac6553bd of the main branch.
The CPython is compiled with --with-pydebug --enable-experimental-jit. OS is ubuntu24.04.
With PYTHON_JIT=0 python ./test.py we successfully get we finished.
However with PYTHON_JIT=1 python ./test.py,
We get

python: Python/optimizer.c:804: _PyJit_translate_single_bytecode_to_trace: Assertion `jump_happened == (target_instr[1].cache & 1)' failed.
Aborted (core dumped)

Code is below

import random
fuzzer_rng = random.Random(1070)
from random import random
from sys import stderr

def uop_harness_f1():
    import gc
    gc.set_threshold(1)

    class _SurferA:

        def __init__(self, val):
            self.val = val

        def __bool__(self):
            self.__class__ = _SurferB
            return True

        def __int__(self):
            self.__class__ = _SurferB
            return int(self.val)

        def __index__(self):
            self.__class__ = _SurferB
            return int(self.val)

        def __add__(self, other):
            self.__class__ = _SurferB
            return self.val + other

    class _SurferB:

        def __init__(self, val):
            self.val = val

        def __bool__(self):
            self.__class__ = _SurferA
            return False

        def __int__(self):
            self.__class__ = _SurferA
            return int(self.val)

        def __index__(self):
            self.__class__ = _SurferA
            return int(self.val)

        def __add__(self, other):
            self.__class__ = _SurferA
            return self.val + other

    class ChaoticIterator_comp_8805:

        def __init__(self, items):
            self._items = list(items)
            self._index = 0

        def __iter__(self):
            return self

        def __next__(self):
            if fuzzer_rng.random() < 0.05:
                self._items.clear()
            if fuzzer_rng.random() < 0.05:
                self._items.extend([999, 'chaos', None])
            if fuzzer_rng.random() >= 0.1:
                return 'unexpected_type_from_iterator'
            if self._index >= len(self._items):
                raise StopIteration
            item = self._items[self._index]
            self._index += 1
            return item
    evil_iter_comp_8805 = ChaoticIterator_comp_8805(range(200))
    try:
        _ = [x + y for x in evil_iter_comp_8805 for y in evil_iter_comp_8805 if evil_iter_comp_8805._items.append(x) or True]
    except Exception:
        pass

for i_f1 in range(300):
    try:
        final_harness_locals = uop_harness_f1()
    except Exception as e:
        print(f'EXCEPTION: {e.__class__.__name__}: {e}', file=stderr)
        pass
print("we finished")

Below is the diff i used to trigger JIT easier

diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h
index ee907ae0534..7fd2c960cc4 100644
--- a/Include/internal/pycore_backoff.h
+++ b/Include/internal/pycore_backoff.h
@@ -125,7 +125,7 @@ trigger_backoff_counter(void)
 // For example, 4095 does not work for the nqueens benchmark on pyperformance
 // 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_VALUE 63
 #define JUMP_BACKWARD_INITIAL_BACKOFF 6
 static inline _Py_BackoffCounter
 initial_jump_backoff_counter(_PyOptimizationConfig *opt_config)
@@ -139,7 +139,7 @@ initial_jump_backoff_counter(_PyOptimizationConfig *opt_config)
  * 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 4000
+#define SIDE_EXIT_INITIAL_VALUE 63
 #define SIDE_EXIT_INITIAL_BACKOFF 6
 
 static inline _Py_BackoffCounter
diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h
index 79a2d60eb78..ac7d9205e74 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -173,7 +173,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp);
 // Used as the threshold to trigger executor invalidation when
 // executor_creation_counter is greater than this value.
 // This value is arbitrary and was not optimized.
-#define JIT_CLEANUP_THRESHOLD 1000
+#define JIT_CLEANUP_THRESHOLD 10000
 
 int _Py_uop_analyze_and_optimize(
     _PyThreadStateImpl *tstate,
diff --git a/Include/internal/pycore_optimizer_types.h b/Include/internal/pycore_optimizer_types.h
index 57c0c828c2a..afe2804eaba 100644
--- a/Include/internal/pycore_optimizer_types.h
+++ b/Include/internal/pycore_optimizer_types.h
@@ -12,7 +12,7 @@ extern "C" {
 #include "pycore_uop.h"  // UOP_MAX_TRACE_LENGTH
 
 // Holds locals, stack, locals, stack ... (in that order)
-#define MAX_ABSTRACT_INTERP_SIZE 512
+#define MAX_ABSTRACT_INTERP_SIZE 8192
 
 #define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5)
 
@@ -23,7 +23,7 @@ extern "C" {
 // progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this
 // is the "maximum amount of polymorphism" that an isolated trace tree can
 // handle before rejoining the rest of the program.
-#define MAX_CHAIN_DEPTH 4
+#define MAX_CHAIN_DEPTH 16
 
 /* Symbols */
 /* See explanation in optimizer_symbols.c */
diff --git a/Python/optimizer.c b/Python/optimizer.c
index bf5d8a28264..acad398ec35 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -534,7 +534,7 @@ guard_ip_uop[MAX_UOP_ID + 1] = {
 
 
 #define CONFIDENCE_RANGE 1000
-#define CONFIDENCE_CUTOFF 333
+#define CONFIDENCE_CUTOFF 100
 
 #ifdef Py_DEBUG
 #define DPRINTF(level, ...) \

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-JITtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions