mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.4'
This commit is contained in:
@@ -418,7 +418,10 @@ static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id n
|
||||
zif->module = EG(current_module);
|
||||
zif->scope = ce;
|
||||
zif->T = ZEND_OBSERVER_ENABLED;
|
||||
if (EG(active)) { // at run-time
|
||||
if (EG(active)) { // at run-time
|
||||
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
|
||||
zif->fn_flags |= ZEND_ACC_PRELOADED;
|
||||
}
|
||||
ZEND_MAP_PTR_INIT(zif->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
|
||||
} else {
|
||||
#ifdef ZTS
|
||||
|
||||
@@ -70,6 +70,9 @@ typedef struct _zend_string zend_string;
|
||||
} while (0)
|
||||
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
|
||||
((void*)(((uintptr_t)(real_base)) + zend_map_ptr_static_size * sizeof(void *) - 1))
|
||||
/* Note: chunked like: [8192..12287][4096..8191][0..4095] */
|
||||
#define ZEND_MAP_PTR_STATIC_NUM_TO_PTR(num) \
|
||||
((void **)CG(map_ptr_real_base) + zend_map_ptr_static_size - ZEND_MM_ALIGNED_SIZE_EX((num) + 1, 4096) + ((num) & 4095))
|
||||
#else
|
||||
# error "Unknown ZEND_MAP_PTR_KIND"
|
||||
#endif
|
||||
|
||||
@@ -2621,6 +2621,7 @@ static void zend_reset_cache_vars(void)
|
||||
ZCSG(restart_pending) = false;
|
||||
ZCSG(force_restart_time) = 0;
|
||||
ZCSG(map_ptr_last) = CG(map_ptr_last);
|
||||
ZCSG(map_ptr_static_last) = zend_map_ptr_static_last;
|
||||
}
|
||||
|
||||
static void accel_reset_pcre_cache(void)
|
||||
@@ -2636,7 +2637,7 @@ static void accel_reset_pcre_cache(void)
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
zend_result accel_activate(INIT_FUNC_ARGS)
|
||||
ZEND_RINIT_FUNCTION(zend_accelerator)
|
||||
{
|
||||
if (!ZCG(enabled) || !accel_startup_ok) {
|
||||
ZCG(accelerator_enabled) = false;
|
||||
@@ -2972,12 +2973,15 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
|
||||
GC_MAKE_PERSISTENT_LOCAL(accel_globals->key);
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
static void accel_globals_dtor(zend_accel_globals *accel_globals)
|
||||
{
|
||||
#ifdef ZTS
|
||||
zend_string_free(accel_globals->key);
|
||||
}
|
||||
#endif
|
||||
if (accel_globals->preloaded_internal_run_time_cache) {
|
||||
pefree(accel_globals->preloaded_internal_run_time_cache, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HUGE_CODE_PAGES
|
||||
# ifndef _WIN32
|
||||
@@ -3466,6 +3470,8 @@ void accel_shutdown(void)
|
||||
if (!ZCG(enabled) || !accel_startup_ok) {
|
||||
#ifdef ZTS
|
||||
ts_free_id(accel_globals_id);
|
||||
#else
|
||||
accel_globals_dtor(&accel_globals);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -3482,6 +3488,8 @@ void accel_shutdown(void)
|
||||
|
||||
#ifdef ZTS
|
||||
ts_free_id(accel_globals_id);
|
||||
#else
|
||||
accel_globals_dtor(&accel_globals);
|
||||
#endif
|
||||
|
||||
if (!_file_cache_only) {
|
||||
@@ -4382,7 +4390,7 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s
|
||||
return new_persistent_script;
|
||||
}
|
||||
|
||||
static void preload_load(void)
|
||||
static void preload_load(size_t orig_map_ptr_static_last)
|
||||
{
|
||||
/* Load into process tables */
|
||||
zend_script *script = &ZCSG(preload_script)->script;
|
||||
@@ -4417,14 +4425,42 @@ static void preload_load(void)
|
||||
if (EG(class_table)) {
|
||||
EG(persistent_classes_count) = EG(class_table)->nNumUsed;
|
||||
}
|
||||
if (CG(map_ptr_last) != ZCSG(map_ptr_last)) {
|
||||
size_t old_map_ptr_last = CG(map_ptr_last);
|
||||
|
||||
size_t old_map_ptr_last = CG(map_ptr_last);
|
||||
if (zend_map_ptr_static_last != ZCSG(map_ptr_static_last) || old_map_ptr_last != ZCSG(map_ptr_last)) {
|
||||
CG(map_ptr_last) = ZCSG(map_ptr_last);
|
||||
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
|
||||
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
|
||||
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(ZCSG(map_ptr_last) + 1, 4096);
|
||||
zend_map_ptr_static_last = ZCSG(map_ptr_static_last);
|
||||
|
||||
/* Grow map_ptr table as needed, but allocate once for static + regular map_ptrs */
|
||||
size_t new_static_size = ZEND_MM_ALIGNED_SIZE_EX(zend_map_ptr_static_last, 4096);
|
||||
if (zend_map_ptr_static_size != new_static_size) {
|
||||
void *new_base = pemalloc((new_static_size + CG(map_ptr_size)) * sizeof(void *), 1);
|
||||
if (CG(map_ptr_real_base)) {
|
||||
memcpy((void **) new_base + new_static_size - zend_map_ptr_static_size, CG(map_ptr_real_base), (old_map_ptr_last + zend_map_ptr_static_size) * sizeof(void *));
|
||||
pefree(CG(map_ptr_real_base), 1);
|
||||
}
|
||||
CG(map_ptr_real_base) = new_base;
|
||||
zend_map_ptr_static_size = new_static_size;
|
||||
} else {
|
||||
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), (zend_map_ptr_static_size + CG(map_ptr_size)) * sizeof(void *), 1);
|
||||
}
|
||||
|
||||
memset((void **) CG(map_ptr_real_base) + zend_map_ptr_static_size + old_map_ptr_last, 0, (CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *));
|
||||
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
|
||||
memset((void **) CG(map_ptr_real_base) + old_map_ptr_last, 0,
|
||||
(CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *));
|
||||
}
|
||||
|
||||
if (orig_map_ptr_static_last != zend_map_ptr_static_last) {
|
||||
/* preloaded static entries currently are all runtime cache pointers, just assign them as such */
|
||||
size_t runtime_cache_size = zend_internal_run_time_cache_reserved_size();
|
||||
ZCG(preloaded_internal_run_time_cache_size) = (zend_map_ptr_static_last - orig_map_ptr_static_last) * runtime_cache_size;
|
||||
char *cache = pemalloc(ZCG(preloaded_internal_run_time_cache_size), 1);
|
||||
ZCG(preloaded_internal_run_time_cache) = cache;
|
||||
|
||||
for (size_t cur_static_map_ptr = orig_map_ptr_static_last; cur_static_map_ptr < zend_map_ptr_static_last; ++cur_static_map_ptr) {
|
||||
*ZEND_MAP_PTR_STATIC_NUM_TO_PTR(cur_static_map_ptr) = cache;
|
||||
cache += runtime_cache_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4433,7 +4469,7 @@ static zend_result accel_preload(const char *config, bool in_child)
|
||||
zend_file_handle file_handle;
|
||||
zend_result ret;
|
||||
char *orig_open_basedir;
|
||||
size_t orig_map_ptr_last;
|
||||
size_t orig_map_ptr_last, orig_map_ptr_static_last;
|
||||
uint32_t orig_compiler_options;
|
||||
|
||||
ZCG(enabled) = false;
|
||||
@@ -4444,6 +4480,7 @@ static zend_result accel_preload(const char *config, bool in_child)
|
||||
accelerator_orig_compile_file = preload_compile_file;
|
||||
|
||||
orig_map_ptr_last = CG(map_ptr_last);
|
||||
orig_map_ptr_static_last = zend_map_ptr_static_last;
|
||||
|
||||
/* Compile and execute preloading script */
|
||||
zend_stream_init_filename(&file_handle, (char *) config);
|
||||
@@ -4623,7 +4660,7 @@ static zend_result accel_preload(const char *config, bool in_child)
|
||||
SHM_PROTECT();
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
preload_load();
|
||||
preload_load(orig_map_ptr_static_last);
|
||||
|
||||
/* Store individual scripts with unlinked classes */
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
@@ -4874,7 +4911,7 @@ static zend_result accel_finish_startup(void)
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
/* Preloading was done in another process */
|
||||
preload_load();
|
||||
preload_load(zend_map_ptr_static_last);
|
||||
zend_shared_alloc_unlock();
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -4902,7 +4939,7 @@ static zend_result accel_finish_startup(void)
|
||||
}
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
preload_load();
|
||||
preload_load(zend_map_ptr_static_last);
|
||||
}
|
||||
|
||||
zend_shared_alloc_unlock();
|
||||
@@ -4916,6 +4953,12 @@ static zend_result accel_finish_startup(void)
|
||||
#endif /* ZEND_WIN32 */
|
||||
}
|
||||
|
||||
static void accel_activate(void) {
|
||||
if (ZCG(preloaded_internal_run_time_cache)) {
|
||||
memset(ZCG(preloaded_internal_run_time_cache), 0, ZCG(preloaded_internal_run_time_cache_size));
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_EXT_API zend_extension zend_extension_entry = {
|
||||
ACCELERATOR_PRODUCT_NAME, /* name */
|
||||
PHP_VERSION, /* version */
|
||||
@@ -4924,7 +4967,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = {
|
||||
"Copyright (c)", /* copyright */
|
||||
accel_startup, /* startup */
|
||||
NULL, /* shutdown */
|
||||
NULL, /* per-script activation */
|
||||
accel_activate, /* per-script activation */
|
||||
#ifdef HAVE_JIT
|
||||
accel_deactivate, /* per-script deactivation */
|
||||
#else
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "zend_extensions.h"
|
||||
#include "zend_compile.h"
|
||||
#include "zend_API.h"
|
||||
|
||||
#include "Optimizer/zend_optimizer.h"
|
||||
#include "zend_accelerator_hash.h"
|
||||
@@ -217,6 +218,8 @@ typedef struct _zend_accel_globals {
|
||||
#ifndef ZEND_WIN32
|
||||
zend_ulong root_hash;
|
||||
#endif
|
||||
void *preloaded_internal_run_time_cache;
|
||||
size_t preloaded_internal_run_time_cache_size;
|
||||
/* preallocated shared-memory block to save current script */
|
||||
void *mem;
|
||||
zend_persistent_script *current_persistent_script;
|
||||
@@ -252,6 +255,7 @@ typedef struct _zend_accel_shared_globals {
|
||||
zend_accel_hash hash; /* hash table for cached scripts */
|
||||
|
||||
size_t map_ptr_last;
|
||||
size_t map_ptr_static_last;
|
||||
|
||||
/* Directives & Maintenance */
|
||||
time_t start_time;
|
||||
@@ -311,7 +315,7 @@ extern const char *zps_api_failure_reason;
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
void accel_shutdown(void);
|
||||
zend_result accel_activate(INIT_FUNC_ARGS);
|
||||
ZEND_RINIT_FUNCTION(zend_accelerator);
|
||||
zend_result accel_post_deactivate(void);
|
||||
void zend_accel_schedule_restart(zend_accel_restart_reason reason);
|
||||
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
|
||||
|
||||
55
ext/opcache/tests/preload_enum_observed.phpt
Normal file
55
ext/opcache/tests/preload_enum_observed.phpt
Normal file
@@ -0,0 +1,55 @@
|
||||
--TEST--
|
||||
Enum preloading with observers
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
zend_test
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.optimization_level=-1
|
||||
opcache.preload={PWD}/preload_enum.inc
|
||||
zend_test.observer.enabled=1
|
||||
zend_test.observer.show_output=1
|
||||
zend_test.observer.observe_all=1
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
spl_autoload_register(static function ($class) {
|
||||
if ($class === 'MyEnum') {
|
||||
require_once(__DIR__ . '/preload_enum.inc');
|
||||
}
|
||||
});
|
||||
|
||||
var_dump(MyEnum::cases());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%spreload_enum.inc' -->
|
||||
<file '%spreload_enum.inc'>
|
||||
<!-- init var_dump() -->
|
||||
<var_dump>
|
||||
enum(MyEnum::Bar)
|
||||
</var_dump>
|
||||
</file '%spreload_enum.inc'>
|
||||
<!-- init '%spreload_enum_observed.php' -->
|
||||
<file '%spreload_enum_observed.php'>
|
||||
<!-- init spl_autoload_register() -->
|
||||
<spl_autoload_register>
|
||||
</spl_autoload_register>
|
||||
<!-- init MyEnum::cases() -->
|
||||
<MyEnum::cases>
|
||||
</MyEnum::cases>
|
||||
<!-- init var_dump() -->
|
||||
<var_dump>
|
||||
array(2) {
|
||||
[0]=>
|
||||
enum(MyEnum::Foo)
|
||||
[1]=>
|
||||
enum(MyEnum::Bar)
|
||||
}
|
||||
</var_dump>
|
||||
</file '%spreload_enum_observed.php'>
|
||||
@@ -559,7 +559,7 @@ static zend_module_entry accel_module_entry = {
|
||||
ext_functions,
|
||||
ZEND_MINIT(zend_accelerator),
|
||||
ZEND_MSHUTDOWN(zend_accelerator),
|
||||
accel_activate,
|
||||
ZEND_RINIT(zend_accelerator),
|
||||
NULL,
|
||||
zend_accel_info,
|
||||
PHP_VERSION,
|
||||
|
||||
@@ -748,7 +748,11 @@ static zend_op_array *zend_persist_class_method(zend_op_array *op_array, zend_cl
|
||||
// Real dynamically created internal functions like enum methods must have their own run_time_cache pointer. They're always on the same scope as their defining class.
|
||||
// However, copies - as caused by inheritance of internal methods - must retain the original run_time_cache pointer, shared with the source function.
|
||||
if (!op_array->scope || (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))) {
|
||||
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
|
||||
if (op_array->fn_flags & ZEND_ACC_PRELOADED) {
|
||||
ZEND_MAP_PTR_NEW_STATIC(op_array->run_time_cache);
|
||||
} else {
|
||||
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1426,6 +1430,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
|
||||
|
||||
if (for_shm) {
|
||||
ZCSG(map_ptr_last) = CG(map_ptr_last);
|
||||
ZCSG(map_ptr_static_last) = zend_map_ptr_static_last;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
|
||||
Reference in New Issue
Block a user