| 
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