Skip to content

Commit 343272e

Browse files
Make internal run_time_cache a persistent allocation
We also add zend_map_ptr_static, so that we do not incur the overhead of constantly recreating the internal run_time_cache pointers on each request. This mechanism might be extended for mutable_data of internal classes too.
1 parent 68ae477 commit 343272e

File tree

8 files changed

+69
-13
lines changed

8 files changed

+69
-13
lines changed

Zend/zend.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
742742
compiler_globals->map_ptr_real_base = base;
743743
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(base);
744744
memset(base, 0, compiler_globals->map_ptr_last * sizeof(void*));
745+
zend_init_internal_run_time_cache();
745746
}
746747
}
747748
/* }}} */
@@ -785,6 +786,9 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
785786
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
786787
compiler_globals->map_ptr_size = 0;
787788
}
789+
if (compiler_globals->internal_run_time_cache) {
790+
pefree(compiler_globals->internal_run_time_cache, 1);
791+
}
788792
}
789793
/* }}} */
790794

@@ -1083,6 +1087,7 @@ zend_result zend_post_startup(void) /* {{{ */
10831087

10841088
zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
10851089
zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
1090+
global_map_ptr_last = compiler_globals->map_ptr_last;
10861091
#endif
10871092

10881093
startup_done = true;
@@ -1113,6 +1118,9 @@ zend_result zend_post_startup(void) /* {{{ */
11131118
if (compiler_globals->map_ptr_real_base) {
11141119
free(compiler_globals->map_ptr_real_base);
11151120
}
1121+
if (compiler_globals->internal_run_time_cache) {
1122+
pefree(compiler_globals->internal_run_time_cache, 1);
1123+
}
11161124
compiler_globals->map_ptr_real_base = NULL;
11171125
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
11181126
if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) {
@@ -1198,6 +1206,9 @@ void zend_shutdown(void) /* {{{ */
11981206
CG(script_encoding_list_size) = 0;
11991207
}
12001208
#endif
1209+
zend_map_ptr_static_last = 0;
1210+
zend_map_ptr_static_size = 0;
1211+
12011212
zend_destroy_rsrc_list_dtors();
12021213

12031214
zend_unload_modules();
@@ -1297,9 +1308,9 @@ ZEND_API void zend_activate(void) /* {{{ */
12971308
init_executor();
12981309
startup_scanner();
12991310
if (CG(map_ptr_last)) {
1300-
memset(CG(map_ptr_real_base), 0, CG(map_ptr_last) * sizeof(void*));
1311+
memset((char *)CG(map_ptr_real_base) + zend_map_ptr_static_size * sizeof(void*), 0, (CG(map_ptr_last) - zend_map_ptr_static_size) * sizeof(void*));
13011312
}
1302-
zend_init_internal_run_time_cache();
1313+
zend_reset_internal_run_time_cache();
13031314
zend_observer_activate();
13041315
}
13051316
/* }}} */
@@ -1984,6 +1995,9 @@ void free_estring(char **str_p) /* {{{ */
19841995
}
19851996
/* }}} */
19861997

1998+
ZEND_API size_t zend_map_ptr_static_size;
1999+
ZEND_API size_t zend_map_ptr_static_last;
2000+
19872001
ZEND_API void zend_map_ptr_reset(void)
19882002
{
19892003
CG(map_ptr_last) = global_map_ptr_last;
@@ -2005,6 +2019,25 @@ ZEND_API void *zend_map_ptr_new(void)
20052019
return ZEND_MAP_PTR_PTR2OFFSET(ptr);
20062020
}
20072021

2022+
ZEND_API void *zend_map_ptr_new_static(void)
2023+
{
2024+
void **ptr;
2025+
2026+
if (zend_map_ptr_static_last >= zend_map_ptr_static_size) {
2027+
CG(map_ptr_last) += 4096;
2028+
zend_map_ptr_static_size += 4096;
2029+
/* Grow map_ptr table */
2030+
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last), 4096);
2031+
/* Note: there are no used non-static map_ptrs yet, hence we don't need to move the whole thing */
2032+
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
2033+
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
2034+
}
2035+
ptr = (void**)CG(map_ptr_real_base) + zend_map_ptr_static_last;
2036+
*ptr = NULL;
2037+
zend_map_ptr_static_last++;
2038+
return ZEND_MAP_PTR_PTR2OFFSET(ptr);
2039+
}
2040+
20082041
ZEND_API void zend_map_ptr_extend(size_t last)
20092042
{
20102043
if (last > CG(map_ptr_last)) {

Zend/zend_API.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2952,7 +2952,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
29522952
if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
29532953
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
29542954
} else {
2955-
ZEND_MAP_PTR_NEW(internal_function->run_time_cache);
2955+
ZEND_MAP_PTR_NEW_STATIC(internal_function->run_time_cache);
29562956
}
29572957
if (ptr->flags) {
29582958
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {

Zend/zend_enum.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id n
421421
if (EG(active)) { // at run-time
422422
ZEND_MAP_PTR_INIT(zif->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
423423
} else {
424-
ZEND_MAP_PTR_NEW(zif->run_time_cache);
424+
ZEND_MAP_PTR_NEW_STATIC(zif->run_time_cache);
425425
}
426426

427427
if (!zend_hash_add_ptr(&ce->function_table, name, zif)) {

Zend/zend_extensions.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,19 +331,22 @@ ZEND_API void zend_init_internal_run_time_cache(void) {
331331
functions += zend_hash_num_elements(&ce->function_table);
332332
} ZEND_HASH_FOREACH_END();
333333

334-
char *ptr = zend_arena_calloc(&CG(arena), functions, rt_size);
334+
size_t alloc_size = functions * rt_size;
335+
char *ptr = pemalloc(alloc_size, 1);
336+
337+
CG(internal_run_time_cache) = ptr;
338+
CG(internal_run_time_cache_size) = alloc_size;
339+
335340
zend_internal_function *zif;
336341
ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) {
337-
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL)
338-
{
342+
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL) {
339343
ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr);
340344
ptr += rt_size;
341345
}
342346
} ZEND_HASH_FOREACH_END();
343347
ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
344348
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, zif) {
345-
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL)
346-
{
349+
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL) {
347350
ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr);
348351
ptr += rt_size;
349352
}
@@ -352,6 +355,12 @@ ZEND_API void zend_init_internal_run_time_cache(void) {
352355
}
353356
}
354357

358+
ZEND_API void zend_reset_internal_run_time_cache(void) {
359+
if (CG(internal_run_time_cache)) {
360+
memset(CG(internal_run_time_cache), 0, CG(internal_run_time_cache_size));
361+
}
362+
}
363+
355364
ZEND_API zend_extension *zend_get_extension(const char *extension_name)
356365
{
357366
zend_llist_element *element;

Zend/zend_extensions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ void zend_shutdown_extensions(void);
149149

150150
ZEND_API size_t zend_internal_run_time_cache_reserved_size(void);
151151
ZEND_API void zend_init_internal_run_time_cache(void);
152+
ZEND_API void zend_reset_internal_run_time_cache(void);
152153

153154
BEGIN_EXTERN_C()
154155
ZEND_API zend_result zend_load_extension(const char *path);

Zend/zend_globals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ struct _zend_compiler_globals {
153153

154154
uint32_t rtd_key_counter;
155155

156+
void *internal_run_time_cache;
157+
uint32_t internal_run_time_cache_size;
158+
156159
zend_stack short_circuiting_opnums;
157160
#ifdef ZTS
158161
uint32_t copied_functions_count;

Zend/zend_map_ptr.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,21 @@ typedef struct _zend_string zend_string;
4242
#define ZEND_MAP_PTR_NEW(ptr) do { \
4343
ZEND_MAP_PTR(ptr) = zend_map_ptr_new(); \
4444
} while (0)
45+
#define ZEND_MAP_PTR_NEW_STATIC(ptr) do { \
46+
ZEND_MAP_PTR(ptr) = zend_map_ptr_new_static(); \
47+
} while (0)
4548

4649
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
4750
# define ZEND_MAP_PTR_NEW_OFFSET() \
48-
((uint32_t)(uintptr_t)zend_map_ptr_new())
51+
((uint32_t)(intptr_t)zend_map_ptr_new())
4952
# define ZEND_MAP_PTR_IS_OFFSET(ptr) \
5053
(((uintptr_t)ZEND_MAP_PTR(ptr)) & 1L)
5154
# define ZEND_MAP_PTR_GET(ptr) \
5255
((ZEND_MAP_PTR_IS_OFFSET(ptr) ? \
5356
ZEND_MAP_PTR_GET_IMM(ptr) : \
5457
((void*)(ZEND_MAP_PTR(ptr)))))
5558
# define ZEND_MAP_PTR_GET_IMM(ptr) \
56-
(*ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)))
59+
(*ZEND_MAP_PTR_OFFSET2PTR((intptr_t)ZEND_MAP_PTR(ptr)))
5760
# define ZEND_MAP_PTR_SET(ptr, val) do { \
5861
if (ZEND_MAP_PTR_IS_OFFSET(ptr)) { \
5962
ZEND_MAP_PTR_SET_IMM(ptr, val); \
@@ -62,11 +65,11 @@ typedef struct _zend_string zend_string;
6265
} \
6366
} while (0)
6467
# define ZEND_MAP_PTR_SET_IMM(ptr, val) do { \
65-
void **__p = ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)); \
68+
void **__p = ZEND_MAP_PTR_OFFSET2PTR((intptr_t)ZEND_MAP_PTR(ptr)); \
6669
*__p = (val); \
6770
} while (0)
6871
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
69-
((void*)(((uintptr_t)(real_base)) - 1))
72+
((void*)(((uintptr_t)(real_base)) + zend_map_ptr_static_size * sizeof(void *) - 1))
7073
#else
7174
# error "Unknown ZEND_MAP_PTR_KIND"
7275
#endif
@@ -75,9 +78,13 @@ BEGIN_EXTERN_C()
7578

7679
ZEND_API void zend_map_ptr_reset(void);
7780
ZEND_API void *zend_map_ptr_new(void);
81+
ZEND_API void *zend_map_ptr_new_static(void);
7882
ZEND_API void zend_map_ptr_extend(size_t last);
7983
ZEND_API void zend_alloc_ce_cache(zend_string *type_name);
8084

85+
ZEND_API extern size_t zend_map_ptr_static_last;
86+
ZEND_API extern size_t zend_map_ptr_static_size;
87+
8188
END_EXTERN_C()
8289

8390
#endif /* ZEND_MAP_PTR_H */

main/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,9 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi
22762276
/* freeze the list of observer fcall_init handlers */
22772277
zend_observer_post_startup();
22782278

2279+
/* freeze the list of persistent internal functions */
2280+
zend_init_internal_run_time_cache();
2281+
22792282
/* Extensions that add engine hooks after this point do so at their own peril */
22802283
zend_finalize_system_id();
22812284

0 commit comments

Comments
 (0)