|
52 | 52 |
|
53 | 53 | #ifdef HAVE_JIT
|
54 | 54 | # include "jit/zend_jit.h"
|
| 55 | +# include "Optimizer/zend_func_info.h" |
| 56 | +# include "Optimizer/zend_call_graph.h" |
55 | 57 | #endif
|
56 | 58 |
|
57 | 59 | #ifndef ZEND_WIN32
|
@@ -4363,6 +4365,39 @@ static void preload_load(void)
|
4363 | 4365 | }
|
4364 | 4366 | }
|
4365 | 4367 |
|
| 4368 | +#if HAVE_JIT |
| 4369 | +static void zend_accel_clear_call_graph_ptrs(zend_op_array *op_array) |
| 4370 | +{ |
| 4371 | + ZEND_ASSERT(ZEND_USER_CODE(op_array->type)); |
| 4372 | + zend_func_info *info = ZEND_FUNC_INFO(op_array); |
| 4373 | + if (info) { |
| 4374 | + info->caller_info = NULL; |
| 4375 | + info->callee_info = NULL; |
| 4376 | + } |
| 4377 | +} |
| 4378 | + |
| 4379 | +static void accel_reset_arena_info(zend_persistent_script *script) |
| 4380 | +{ |
| 4381 | + zend_op_array *op_array; |
| 4382 | + zend_class_entry *ce; |
| 4383 | + |
| 4384 | + zend_accel_clear_call_graph_ptrs(&script->script.main_op_array); |
| 4385 | + ZEND_HASH_MAP_FOREACH_PTR(&script->script.function_table, op_array) { |
| 4386 | + zend_accel_clear_call_graph_ptrs(op_array); |
| 4387 | + } ZEND_HASH_FOREACH_END(); |
| 4388 | + ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { |
| 4389 | + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { |
| 4390 | + if (op_array->scope == ce |
| 4391 | + && op_array->type == ZEND_USER_FUNCTION |
| 4392 | + && !(op_array->fn_flags & ZEND_ACC_ABSTRACT) |
| 4393 | + && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { |
| 4394 | + zend_accel_clear_call_graph_ptrs(op_array); |
| 4395 | + } |
| 4396 | + } ZEND_HASH_FOREACH_END(); |
| 4397 | + } ZEND_HASH_FOREACH_END(); |
| 4398 | +} |
| 4399 | +#endif |
| 4400 | + |
4366 | 4401 | static zend_result accel_preload(const char *config, bool in_child)
|
4367 | 4402 | {
|
4368 | 4403 | zend_file_handle file_handle;
|
@@ -4568,6 +4603,18 @@ static zend_result accel_preload(const char *config, bool in_child)
|
4568 | 4603 | } ZEND_HASH_FOREACH_END();
|
4569 | 4604 | ZCSG(saved_scripts)[i] = NULL;
|
4570 | 4605 |
|
| 4606 | +#if HAVE_JIT |
| 4607 | + /* During persisting, the JIT may trigger and fill in the call graph. |
| 4608 | + * The call graph info is allocated on the arena which will be gone after preloading. |
| 4609 | + * To prevent invalid accesses during normal requests, the arena data should be cleared. |
| 4610 | + * This has to be done after all scripts have been persisted because shared op arrays between |
| 4611 | + * scripts can change the call graph. */ |
| 4612 | + accel_reset_arena_info(ZCSG(preload_script)); |
| 4613 | + for (zend_persistent_script **scripts = ZCSG(saved_scripts); *scripts; scripts++) { |
| 4614 | + accel_reset_arena_info(*scripts); |
| 4615 | + } |
| 4616 | +#endif |
| 4617 | + |
4571 | 4618 | zend_shared_alloc_save_state();
|
4572 | 4619 | accel_interned_strings_save_state();
|
4573 | 4620 |
|
|
0 commit comments