diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 52f7d0d2b3df95..80e4ae603a2614 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -134,6 +134,34 @@ jobs: make all --jobs 4 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + jit-with-disabled-gil: + name: Free-Threaded (Debug) + needs: interpreter + runs-on: ubuntu-24.04 + timeout-minutes: 90 + strategy: + fail-fast: false + matrix: + llvm: + - 19 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Build with JIT enabled and GIL disabled + run: | + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} + export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" + ./configure --enable-experimental-jit --with-pydebug --disable-gil + make all --jobs 4 + - name: Run tests + run: | + ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + continue-on-error: true + no-opt-jit: name: JIT without optimizations (Debug) needs: interpreter @@ -160,31 +188,3 @@ jobs: - name: Run tests without optimizations run: | PYTHON_UOPS_OPTIMIZE=0 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - - # XXX: GH-133171 - # jit-with-disabled-gil: - # name: Free-Threaded (Debug) - # needs: interpreter - # runs-on: ubuntu-24.04 - # timeout-minutes: 90 - # strategy: - # fail-fast: false - # matrix: - # llvm: - # - 19 - # steps: - # - uses: actions/checkout@v4 - # with: - # persist-credentials: false - # - uses: actions/setup-python@v5 - # with: - # python-version: '3.11' - # - name: Build with JIT enabled and GIL disabled - # run: | - # sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} - # export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - # ./configure --enable-experimental-jit --with-pydebug --disable-gil - # make all --jobs 4 - # - name: Run tests - # run: | - # ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index c4e8f10fe05276..062834368bcd29 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -464,6 +464,12 @@ PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct) PyStackRef_CLOSE(ref); } +static inline int +PyStackRef_RefcountOnObject(_PyStackRef ref) +{ + return (ref.bits & Py_TAG_REFCNT) == 0; +} + static inline _PyStackRef PyStackRef_DUP(_PyStackRef stackref) { diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 74025ffe9cedc9..418bf3d33e077e 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2940,9 +2940,10 @@ dummy_func( }; tier1 op(_SPECIALIZE_JUMP_BACKWARD, (--)) { - #if ENABLE_SPECIALIZATION + #if ENABLE_SPECIALIZATION_FT if (this_instr->op.code == JUMP_BACKWARD) { - this_instr->op.code = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT; + uint8_t desired = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT; + FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, desired); // Need to re-dispatch so the warmup counter isn't off by one: next_instr = this_instr; DISPATCH_SAME_OPARG(); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index c1f6f5c85cdd88..fc10f56d621d01 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -7589,9 +7589,10 @@ /* Skip 1 cache entry */ // _SPECIALIZE_JUMP_BACKWARD { - #if ENABLE_SPECIALIZATION + #if ENABLE_SPECIALIZATION_FT if (this_instr->op.code == JUMP_BACKWARD) { - this_instr->op.code = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT; + uint8_t desired = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT; + FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, desired); next_instr = this_instr; DISPATCH_SAME_OPARG(); } diff --git a/Python/optimizer.c b/Python/optimizer.c index 53f1500f3989a4..7b76cddeabff44 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -119,6 +119,7 @@ _PyOptimizer_Optimize( PyInterpreterState *interp = _PyInterpreterState_GET(); assert(interp->jit); assert(!interp->compiling); +#ifndef Py_GIL_DISABLED interp->compiling = true; // The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must* // make progress in order to avoid infinite loops or excessively-long @@ -160,6 +161,9 @@ _PyOptimizer_Optimize( assert((*executor_ptr)->vm_data.valid); interp->compiling = false; return 1; +#else + return 0; +#endif } static _PyExecutorObject * diff --git a/configure b/configure index 30562de4418516..bb63895417f6f7 100755 --- a/configure +++ b/configure @@ -10891,7 +10891,8 @@ printf "%s\n" "$tier2_flags $jit_flags" >&6; } if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then # GH-133171: This configuration builds the JIT but never actually uses it, # which is surprising (and strictly worse than not building it at all): - as_fn_error $? "--enable-experimental-jit cannot be used with --disable-gil." "$LINENO" 5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-experimental-jit does not work correctly with --disable-gil." >&5 +printf "%s\n" "$as_me: WARNING: --enable-experimental-jit does not work correctly with --disable-gil." >&2;} fi case "$ac_cv_cc_name" in diff --git a/configure.ac b/configure.ac index ac84ac65efb5c0..f60fe6bcee599e 100644 --- a/configure.ac +++ b/configure.ac @@ -2799,7 +2799,7 @@ AC_MSG_RESULT([$tier2_flags $jit_flags]) if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then # GH-133171: This configuration builds the JIT but never actually uses it, # which is surprising (and strictly worse than not building it at all): - AC_MSG_ERROR([--enable-experimental-jit cannot be used with --disable-gil.]) + AC_MSG_WARN([--enable-experimental-jit does not work correctly with --disable-gil.]) fi case "$ac_cv_cc_name" in