Skip to content

Fix GH-17770: support opcache.file_cache with JIT - #21219

Open
gregharmon wants to merge 2 commits into
php:masterfrom
gregharmon:codex/gh-17770-file-cache-jit
Open

gregharmon wants to merge 2 commits into
php:masterfrom
gregharmon:codex/gh-17770-file-cache-jit

Conversation

@gregharmon

@gregharmon gregharmon commented Feb 15, 2026 •

Copy link
Copy Markdown

Summary

Allow opcache.file_cache to persist scripts while JIT is enabled. The file contains bytecode and stable VM handlers; it does not contain generated machine code or process-local JIT metadata.

When a file-cached script is loaded into shared memory, rebuild its JIT state. Scripts loaded into process memory continue to run without JIT, including opcache.file_cache_only mode.

Changes

  • Restore original VM handlers from JIT metadata while serializing a private copy. For script-load JIT, rebuild only handlers that point into generated JIT code.
  • Clear the function-info slot in the serialized copy and remove the unconditional JIT write guard.
  • Initialize the JIT translation table and rebuild JIT after loading bytecode from disk into shared memory.
  • Add a PHPT regression test for script-load, first-exec, hot-counter, and tracing JIT. It checks the file write, loads the cached bytecode in a separate process after changing the source, and checks that a shared-memory load generates JIT code again.

Validation

  • Built PHP 8.7.0-dev on macOS arm64 with OPcache JIT enabled.
  • Passed gh17770_file_cache.phpt, gh16979_check_file_cache_function.phpt, and gh18136.phpt.
  • file_cache_frameless_handler.phpt skipped locally because the minimal build did not include dl_test.
  • Cross-platform CI is running on this PR.

@gregharmon

Copy link
Copy Markdown
Author

Addressed the Windows CI failure in the new GH-17770 regression test.

Update in ext/opcache/tests/gh17770_jit_file_cache_write.phpt:

  • Switched opcache.file_cache to a quoted dedicated path: {PWD}/gh17770_cache
  • Pre-creates that directory in --SKIPIF--
  • Keeps the test hermetic by cleaning the dedicated cache directory in --CLEAN--
  • Uses opcache_is_script_cached_in_file_cache() for direct script-level assertion

This keeps the regression intent unchanged while avoiding startup/path issues on Windows workers.

@dstogov

dstogov commented Feb 16, 2026

Copy link
Copy Markdown
Member

This preserves the intended model: file cache stores OPcache bytecode/metadata only; JIT machine code is not persisted and is rebuilt at runtime as usual.

JIT compilation takes time. And it's not going to be profitable in case we re-do it on each request.
I suppose, file_cache without JIT should be faster when with JIT.

Probably, this change may be helpful for some cases - e.g rare opcache resets, but it's probably not a big problem to recompile php from sources. In case of often resets, enabling JIT will probably increase CPU load and for file_cache_only increase it significantly.

@iluuu1994

iluuu1994 commented Mar 13, 2026 •

Copy link
Copy Markdown
Member

@dstogov How would you like to proceed here? This seems like a reasonable change to me. File cache can be used to reduce cache stampede, this applies even when JIT is enabled. But if you're against this change, the PR should be closed.

@dstogov

dstogov commented Mar 16, 2026

Copy link
Copy Markdown
Member

I'm not completely against this PR.
I think JIT should be disabled when file_cache_only is set.

@dstogov

dstogov commented Mar 16, 2026

Copy link
Copy Markdown
Member

I'm not completely against this PR. I think JIT should be disabled when file_cache_only is set.

Better, JIT should be disabled for scripts loaded from file-cache, but not loaded into shared memory.

@splitice

splitice commented Oct 11, 2026 •

Copy link
Copy Markdown

Is there some reason this can't be merged. It seems like it does the correct thing.

A more comprehensive solution might be to seperate JIT metadata from the opcache opcode data entirely, this could potentially even allow on disk storage of JIT (useful for same machine, multiple invokation e.g CLI).

@splitice

Copy link
Copy Markdown

@gregharmon I tested this against a PHP 5.6 base (unfortunately jit is pretty broken in 5.5 under our test matrix) against a variety of different tools (phan, phpstan, phpunit, etc) and internal projects.

Ended up re-working this concept slightly as I was recording crashes.

AI refused to review my work due to lack of Daybreak approval (working on it) so potentially it contains a defect I havent been able to spot.

This patch is still under review on our end.

0001-jit-with-file-cache-v2.patch

In PR form I would strip the comments but I retained for @gregharmon's understanding.

@splitice

Copy link
Copy Markdown

Also is there some project of PHP JIT regression tests? It feels like this kind of issue should be automatedly tested.

@gregharmon

Copy link
Copy Markdown
Author

I have Daybreak, working on an update.

@gregharmon
gregharmon force-pushed the codex/gh-17770-file-cache-jit branch from 3edc2b7 to f195f22 Compare October 19, 2026 03:21
Restore original VM handlers and clear process-local JIT metadata in the
serialized copy before writing bytecode to disk.

Rebuild JIT when a cached script is loaded into shared memory. Keep JIT off
for process-local file cache loads.

Cover disk writes and reloads across four JIT trigger modes.

Co-authored-by: Mathew Heard <mheard@x4b.net>
@gregharmon
gregharmon force-pushed the codex/gh-17770-file-cache-jit branch from f195f22 to 22ecf2a Compare October 19, 2026 03:22
@gregharmon gregharmon changed the title Fix GH-17770: allow opcache.file_cache writes when JIT is enabled Fix GH-17770: support opcache.file_cache with JIT Oct 19, 2026
Restore the original VM handler in place in the serialized copy.
Specialized handlers such as ASSIGN_DIM read the next OP_DATA operand
type. A stack copy of the opline does not have that neighbour, so the
file cache stored an invalid handler and failed to load.

Add an array assignment to the phpGH-17770 regression test.
@splitice

Copy link
Copy Markdown

😅 My PHP opcode knowledge is a bit rusty clearly.

I'll give this a run through the known failures from last time.

@splitice

Copy link
Copy Markdown

That passes against my matrix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants