diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 79c7668ba5e9..3df9eed46ca0 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4755,6 +4755,9 @@ static zend_result accel_preload(const char *config, bool in_child) zend_shared_alloc_save_state(); accel_interned_strings_save_state(); +#ifdef HAVE_JIT + zend_jit_save_restart_point(); +#endif SHM_PROTECT(); HANDLE_UNBLOCK_INTERRUPTIONS(); diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index a958a2453c4e..47313fd48d66 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3723,10 +3723,7 @@ void zend_jit_startup(void *buf, size_t size, bool reattached) zend_jit_trace_startup(reattached); - zend_jit_unprotect(); - /* save JIT buffer pos */ - dasm_ptr[1] = dasm_ptr[0]; - zend_jit_protect(); + zend_jit_save_restart_point(); } void zend_jit_shutdown(void) @@ -3908,4 +3905,15 @@ void zend_jit_restart(void) } } +/* Saves the current JIT buffer position as the one zend_jit_restart() rewinds to, + * so that the code generated so far is kept across restarts */ +void zend_jit_save_restart_point(void) +{ + if (dasm_ptr) { + zend_jit_unprotect(); + dasm_ptr[1] = dasm_ptr[0]; + zend_jit_protect(); + } +} + #endif /* HAVE_JIT */ diff --git a/ext/opcache/jit/zend_jit.h b/ext/opcache/jit/zend_jit.h index 9178d340a0ed..f2d2c8a7d184 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -167,6 +167,7 @@ void zend_jit_deactivate(void); ZEND_EXT_API void zend_jit_status(zval *ret); ZEND_EXT_API void zend_jit_blacklist_function(zend_op_array *op_array); void zend_jit_restart(void); +void zend_jit_save_restart_point(void); #define ZREG_LOAD (1<<0) #define ZREG_STORE (1<<1) diff --git a/ext/opcache/tests/jit/preload_restart_function_jit.phpt b/ext/opcache/tests/jit/preload_restart_function_jit.phpt new file mode 100644 index 000000000000..5571b52dfc25 --- /dev/null +++ b/ext/opcache/tests/jit/preload_restart_function_jit.phpt @@ -0,0 +1,82 @@ +--TEST-- +Preloaded functions JIT-compiled on script load must survive an OPcache restart +--EXTENSIONS-- +opcache +--SKIPIF-- + +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=disable +opcache.jit_buffer_size=16M +--CONFLICTS-- +server +--FILE-- +> 2); + } + return $s; +} +function preloaded_str(string $x): string { + return strrev($x) . strlen($x); +} +PHP); + +file_put_contents($dir . '/call.php', <<<'PHP' + +--CLEAN-- + +--EXPECT-- +1502868 olleh5 +bool(true) +1289143 +1502868 olleh5 +1502868 olleh5