Skip to content

Commit bcd7222

Browse files
committed
Merge branch 'PHP-8.4'
2 parents 0610122 + 53fa98e commit bcd7222

File tree

7 files changed

+132
-19
lines changed

7 files changed

+132
-19
lines changed

Zend/zend_enum.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,10 @@ static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id n
418418
zif->module = EG(current_module);
419419
zif->scope = ce;
420420
zif->T = ZEND_OBSERVER_ENABLED;
421-
if (EG(active)) { // at run-time
421+
if (EG(active)) { // at run-time
422+
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
423+
zif->fn_flags |= ZEND_ACC_PRELOADED;
424+
}
422425
ZEND_MAP_PTR_INIT(zif->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
423426
} else {
424427
#ifdef ZTS

Zend/zend_map_ptr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ typedef struct _zend_string zend_string;
7070
} while (0)
7171
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
7272
((void*)(((uintptr_t)(real_base)) + zend_map_ptr_static_size * sizeof(void *) - 1))
73+
/* Note: chunked like: [8192..12287][4096..8191][0..4095] */
74+
#define ZEND_MAP_PTR_STATIC_NUM_TO_PTR(num) \
75+
((void **)CG(map_ptr_real_base) + zend_map_ptr_static_size - ZEND_MM_ALIGNED_SIZE_EX((num) + 1, 4096) + ((num) & 4095))
7376
#else
7477
# error "Unknown ZEND_MAP_PTR_KIND"
7578
#endif

ext/opcache/ZendAccelerator.c

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,6 +2621,7 @@ static void zend_reset_cache_vars(void)
26212621
ZCSG(restart_pending) = false;
26222622
ZCSG(force_restart_time) = 0;
26232623
ZCSG(map_ptr_last) = CG(map_ptr_last);
2624+
ZCSG(map_ptr_static_last) = zend_map_ptr_static_last;
26242625
}
26252626

26262627
static void accel_reset_pcre_cache(void)
@@ -2636,7 +2637,7 @@ static void accel_reset_pcre_cache(void)
26362637
} ZEND_HASH_FOREACH_END();
26372638
}
26382639

2639-
zend_result accel_activate(INIT_FUNC_ARGS)
2640+
ZEND_RINIT_FUNCTION(zend_accelerator)
26402641
{
26412642
if (!ZCG(enabled) || !accel_startup_ok) {
26422643
ZCG(accelerator_enabled) = false;
@@ -2972,12 +2973,15 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
29722973
GC_MAKE_PERSISTENT_LOCAL(accel_globals->key);
29732974
}
29742975

2975-
#ifdef ZTS
29762976
static void accel_globals_dtor(zend_accel_globals *accel_globals)
29772977
{
2978+
#ifdef ZTS
29782979
zend_string_free(accel_globals->key);
2979-
}
29802980
#endif
2981+
if (accel_globals->preloaded_internal_run_time_cache) {
2982+
pefree(accel_globals->preloaded_internal_run_time_cache, 1);
2983+
}
2984+
}
29812985

29822986
#ifdef HAVE_HUGE_CODE_PAGES
29832987
# ifndef _WIN32
@@ -3466,6 +3470,8 @@ void accel_shutdown(void)
34663470
if (!ZCG(enabled) || !accel_startup_ok) {
34673471
#ifdef ZTS
34683472
ts_free_id(accel_globals_id);
3473+
#else
3474+
accel_globals_dtor(&accel_globals);
34693475
#endif
34703476
return;
34713477
}
@@ -3482,6 +3488,8 @@ void accel_shutdown(void)
34823488

34833489
#ifdef ZTS
34843490
ts_free_id(accel_globals_id);
3491+
#else
3492+
accel_globals_dtor(&accel_globals);
34853493
#endif
34863494

34873495
if (!_file_cache_only) {
@@ -4382,7 +4390,7 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s
43824390
return new_persistent_script;
43834391
}
43844392

4385-
static void preload_load(void)
4393+
static void preload_load(size_t orig_map_ptr_static_last)
43864394
{
43874395
/* Load into process tables */
43884396
zend_script *script = &ZCSG(preload_script)->script;
@@ -4417,14 +4425,42 @@ static void preload_load(void)
44174425
if (EG(class_table)) {
44184426
EG(persistent_classes_count) = EG(class_table)->nNumUsed;
44194427
}
4420-
if (CG(map_ptr_last) != ZCSG(map_ptr_last)) {
4421-
size_t old_map_ptr_last = CG(map_ptr_last);
4428+
4429+
size_t old_map_ptr_last = CG(map_ptr_last);
4430+
if (zend_map_ptr_static_last != ZCSG(map_ptr_static_last) || old_map_ptr_last != ZCSG(map_ptr_last)) {
44224431
CG(map_ptr_last) = ZCSG(map_ptr_last);
4423-
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
4424-
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
4432+
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(ZCSG(map_ptr_last) + 1, 4096);
4433+
zend_map_ptr_static_last = ZCSG(map_ptr_static_last);
4434+
4435+
/* Grow map_ptr table as needed, but allocate once for static + regular map_ptrs */
4436+
size_t new_static_size = ZEND_MM_ALIGNED_SIZE_EX(zend_map_ptr_static_last, 4096);
4437+
if (zend_map_ptr_static_size != new_static_size) {
4438+
void *new_base = pemalloc((new_static_size + CG(map_ptr_size)) * sizeof(void *), 1);
4439+
if (CG(map_ptr_real_base)) {
4440+
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 *));
4441+
pefree(CG(map_ptr_real_base), 1);
4442+
}
4443+
CG(map_ptr_real_base) = new_base;
4444+
zend_map_ptr_static_size = new_static_size;
4445+
} else {
4446+
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), (zend_map_ptr_static_size + CG(map_ptr_size)) * sizeof(void *), 1);
4447+
}
4448+
4449+
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 *));
44254450
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
4426-
memset((void **) CG(map_ptr_real_base) + old_map_ptr_last, 0,
4427-
(CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *));
4451+
}
4452+
4453+
if (orig_map_ptr_static_last != zend_map_ptr_static_last) {
4454+
/* preloaded static entries currently are all runtime cache pointers, just assign them as such */
4455+
size_t runtime_cache_size = zend_internal_run_time_cache_reserved_size();
4456+
ZCG(preloaded_internal_run_time_cache_size) = (zend_map_ptr_static_last - orig_map_ptr_static_last) * runtime_cache_size;
4457+
char *cache = pemalloc(ZCG(preloaded_internal_run_time_cache_size), 1);
4458+
ZCG(preloaded_internal_run_time_cache) = cache;
4459+
4460+
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) {
4461+
*ZEND_MAP_PTR_STATIC_NUM_TO_PTR(cur_static_map_ptr) = cache;
4462+
cache += runtime_cache_size;
4463+
}
44284464
}
44294465
}
44304466

@@ -4433,7 +4469,7 @@ static zend_result accel_preload(const char *config, bool in_child)
44334469
zend_file_handle file_handle;
44344470
zend_result ret;
44354471
char *orig_open_basedir;
4436-
size_t orig_map_ptr_last;
4472+
size_t orig_map_ptr_last, orig_map_ptr_static_last;
44374473
uint32_t orig_compiler_options;
44384474

44394475
ZCG(enabled) = false;
@@ -4444,6 +4480,7 @@ static zend_result accel_preload(const char *config, bool in_child)
44444480
accelerator_orig_compile_file = preload_compile_file;
44454481

44464482
orig_map_ptr_last = CG(map_ptr_last);
4483+
orig_map_ptr_static_last = zend_map_ptr_static_last;
44474484

44484485
/* Compile and execute preloading script */
44494486
zend_stream_init_filename(&file_handle, (char *) config);
@@ -4623,7 +4660,7 @@ static zend_result accel_preload(const char *config, bool in_child)
46234660
SHM_PROTECT();
46244661
HANDLE_UNBLOCK_INTERRUPTIONS();
46254662

4626-
preload_load();
4663+
preload_load(orig_map_ptr_static_last);
46274664

46284665
/* Store individual scripts with unlinked classes */
46294666
HANDLE_BLOCK_INTERRUPTIONS();
@@ -4874,7 +4911,7 @@ static zend_result accel_finish_startup(void)
48744911

48754912
if (ZCSG(preload_script)) {
48764913
/* Preloading was done in another process */
4877-
preload_load();
4914+
preload_load(zend_map_ptr_static_last);
48784915
zend_shared_alloc_unlock();
48794916
return SUCCESS;
48804917
}
@@ -4902,7 +4939,7 @@ static zend_result accel_finish_startup(void)
49024939
}
49034940

49044941
if (ZCSG(preload_script)) {
4905-
preload_load();
4942+
preload_load(zend_map_ptr_static_last);
49064943
}
49074944

49084945
zend_shared_alloc_unlock();
@@ -4916,6 +4953,12 @@ static zend_result accel_finish_startup(void)
49164953
#endif /* ZEND_WIN32 */
49174954
}
49184955

4956+
static void accel_activate(void) {
4957+
if (ZCG(preloaded_internal_run_time_cache)) {
4958+
memset(ZCG(preloaded_internal_run_time_cache), 0, ZCG(preloaded_internal_run_time_cache_size));
4959+
}
4960+
}
4961+
49194962
ZEND_EXT_API zend_extension zend_extension_entry = {
49204963
ACCELERATOR_PRODUCT_NAME, /* name */
49214964
PHP_VERSION, /* version */
@@ -4924,7 +4967,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = {
49244967
"Copyright (c)", /* copyright */
49254968
accel_startup, /* startup */
49264969
NULL, /* shutdown */
4927-
NULL, /* per-script activation */
4970+
accel_activate, /* per-script activation */
49284971
#ifdef HAVE_JIT
49294972
accel_deactivate, /* per-script deactivation */
49304973
#else

ext/opcache/ZendAccelerator.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050

5151
#include "zend_extensions.h"
5252
#include "zend_compile.h"
53+
#include "zend_API.h"
5354

5455
#include "Optimizer/zend_optimizer.h"
5556
#include "zend_accelerator_hash.h"
@@ -217,6 +218,8 @@ typedef struct _zend_accel_globals {
217218
#ifndef ZEND_WIN32
218219
zend_ulong root_hash;
219220
#endif
221+
void *preloaded_internal_run_time_cache;
222+
size_t preloaded_internal_run_time_cache_size;
220223
/* preallocated shared-memory block to save current script */
221224
void *mem;
222225
zend_persistent_script *current_persistent_script;
@@ -252,6 +255,7 @@ typedef struct _zend_accel_shared_globals {
252255
zend_accel_hash hash; /* hash table for cached scripts */
253256

254257
size_t map_ptr_last;
258+
size_t map_ptr_static_last;
255259

256260
/* Directives & Maintenance */
257261
time_t start_time;
@@ -311,7 +315,7 @@ extern const char *zps_api_failure_reason;
311315
BEGIN_EXTERN_C()
312316

313317
void accel_shutdown(void);
314-
zend_result accel_activate(INIT_FUNC_ARGS);
318+
ZEND_RINIT_FUNCTION(zend_accelerator);
315319
zend_result accel_post_deactivate(void);
316320
void zend_accel_schedule_restart(zend_accel_restart_reason reason);
317321
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Enum preloading with observers
3+
--EXTENSIONS--
4+
opcache
5+
zend_test
6+
--INI--
7+
opcache.enable=1
8+
opcache.enable_cli=1
9+
opcache.optimization_level=-1
10+
opcache.preload={PWD}/preload_enum.inc
11+
zend_test.observer.enabled=1
12+
zend_test.observer.show_output=1
13+
zend_test.observer.observe_all=1
14+
--SKIPIF--
15+
<?php
16+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
17+
?>
18+
--FILE--
19+
<?php
20+
21+
spl_autoload_register(static function ($class) {
22+
if ($class === 'MyEnum') {
23+
require_once(__DIR__ . '/preload_enum.inc');
24+
}
25+
});
26+
27+
var_dump(MyEnum::cases());
28+
29+
?>
30+
--EXPECTF--
31+
<!-- init '%spreload_enum.inc' -->
32+
<file '%spreload_enum.inc'>
33+
<!-- init var_dump() -->
34+
<var_dump>
35+
enum(MyEnum::Bar)
36+
</var_dump>
37+
</file '%spreload_enum.inc'>
38+
<!-- init '%spreload_enum_observed.php' -->
39+
<file '%spreload_enum_observed.php'>
40+
<!-- init spl_autoload_register() -->
41+
<spl_autoload_register>
42+
</spl_autoload_register>
43+
<!-- init MyEnum::cases() -->
44+
<MyEnum::cases>
45+
</MyEnum::cases>
46+
<!-- init var_dump() -->
47+
<var_dump>
48+
array(2) {
49+
[0]=>
50+
enum(MyEnum::Foo)
51+
[1]=>
52+
enum(MyEnum::Bar)
53+
}
54+
</var_dump>
55+
</file '%spreload_enum_observed.php'>

ext/opcache/zend_accelerator_module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ static zend_module_entry accel_module_entry = {
559559
ext_functions,
560560
ZEND_MINIT(zend_accelerator),
561561
ZEND_MSHUTDOWN(zend_accelerator),
562-
accel_activate,
562+
ZEND_RINIT(zend_accelerator),
563563
NULL,
564564
zend_accel_info,
565565
PHP_VERSION,

ext/opcache/zend_persist.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,11 @@ static zend_op_array *zend_persist_class_method(zend_op_array *op_array, zend_cl
748748
// 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.
749749
// However, copies - as caused by inheritance of internal methods - must retain the original run_time_cache pointer, shared with the source function.
750750
if (!op_array->scope || (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))) {
751-
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
751+
if (op_array->fn_flags & ZEND_ACC_PRELOADED) {
752+
ZEND_MAP_PTR_NEW_STATIC(op_array->run_time_cache);
753+
} else {
754+
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
755+
}
752756
}
753757
}
754758
}
@@ -1426,6 +1430,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
14261430

14271431
if (for_shm) {
14281432
ZCSG(map_ptr_last) = CG(map_ptr_last);
1433+
ZCSG(map_ptr_static_last) = zend_map_ptr_static_last;
14291434
}
14301435

14311436
#ifdef HAVE_JIT

0 commit comments

Comments
 (0)