| 
56 | 56 | 
 
  | 
57 | 57 | #ifdef HAVE_JIT  | 
58 | 58 | # include "jit/zend_jit.h"  | 
 | 59 | +# include "Optimizer/zend_func_info.h"  | 
 | 60 | +# include "Optimizer/zend_call_graph.h"  | 
59 | 61 | #endif  | 
60 | 62 | 
 
  | 
61 | 63 | #ifndef ZEND_WIN32  | 
@@ -4471,6 +4473,39 @@ static void preload_load(size_t orig_map_ptr_static_last)  | 
4471 | 4473 | 	}  | 
4472 | 4474 | }  | 
4473 | 4475 | 
 
  | 
 | 4476 | +#if HAVE_JIT  | 
 | 4477 | +static void zend_accel_clear_call_graph_ptrs(zend_op_array *op_array)  | 
 | 4478 | +{  | 
 | 4479 | +	ZEND_ASSERT(ZEND_USER_CODE(op_array->type));  | 
 | 4480 | +	zend_func_info *info = ZEND_FUNC_INFO(op_array);  | 
 | 4481 | +	if (info) {  | 
 | 4482 | +		info->caller_info = NULL;  | 
 | 4483 | +		info->callee_info = NULL;  | 
 | 4484 | +	}  | 
 | 4485 | +}  | 
 | 4486 | + | 
 | 4487 | +static void accel_reset_arena_info(zend_persistent_script *script)  | 
 | 4488 | +{  | 
 | 4489 | +	zend_op_array *op_array;  | 
 | 4490 | +	zend_class_entry *ce;  | 
 | 4491 | + | 
 | 4492 | +	zend_accel_clear_call_graph_ptrs(&script->script.main_op_array);  | 
 | 4493 | +	ZEND_HASH_MAP_FOREACH_PTR(&script->script.function_table, op_array) {  | 
 | 4494 | +		zend_accel_clear_call_graph_ptrs(op_array);  | 
 | 4495 | +	} ZEND_HASH_FOREACH_END();  | 
 | 4496 | +	ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) {  | 
 | 4497 | +		ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {  | 
 | 4498 | +			if (op_array->scope == ce  | 
 | 4499 | +			 && op_array->type == ZEND_USER_FUNCTION  | 
 | 4500 | +			 && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)  | 
 | 4501 | +			 && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {  | 
 | 4502 | +				zend_accel_clear_call_graph_ptrs(op_array);  | 
 | 4503 | +			}  | 
 | 4504 | +		} ZEND_HASH_FOREACH_END();  | 
 | 4505 | +	} ZEND_HASH_FOREACH_END();  | 
 | 4506 | +}  | 
 | 4507 | +#endif  | 
 | 4508 | + | 
4474 | 4509 | static zend_result accel_preload(const char *config, bool in_child)  | 
4475 | 4510 | {  | 
4476 | 4511 | 	zend_file_handle file_handle;  | 
@@ -4683,6 +4718,18 @@ static zend_result accel_preload(const char *config, bool in_child)  | 
4683 | 4718 | 		} ZEND_HASH_FOREACH_END();  | 
4684 | 4719 | 		ZCSG(saved_scripts)[i] = NULL;  | 
4685 | 4720 | 
 
  | 
 | 4721 | +#if HAVE_JIT  | 
 | 4722 | +		/* During persisting, the JIT may trigger and fill in the call graph.  | 
 | 4723 | +		 * The call graph info is allocated on the arena which will be gone after preloading.  | 
 | 4724 | +		 * To prevent invalid accesses during normal requests, the arena data should be cleared.  | 
 | 4725 | +		 * This has to be done after all scripts have been persisted because shared op arrays between  | 
 | 4726 | +		 * scripts can change the call graph. */  | 
 | 4727 | +		accel_reset_arena_info(ZCSG(preload_script));  | 
 | 4728 | +		for (zend_persistent_script **scripts = ZCSG(saved_scripts); *scripts; scripts++) {  | 
 | 4729 | +			accel_reset_arena_info(*scripts);  | 
 | 4730 | +		}  | 
 | 4731 | +#endif  | 
 | 4732 | + | 
4686 | 4733 | 		zend_shared_alloc_save_state();  | 
4687 | 4734 | 		accel_interned_strings_save_state();  | 
4688 | 4735 | 
 
  | 
 | 
0 commit comments