From ee069a337bb693b92bf85e0ceb39502a4ef0e80f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Mar 2023 01:50:10 +0100 Subject: [PATCH 1/3] Shrink some commonly used structs by reordering members Struct members require some alignment based on their type. This means that if a struct member is not aligned, there will be a hole created by the compiler in the struct, which is wasted space. This patch reorders some of the most commonly used structs, but in such a way that the fields which were in the same cache line still belong together. The only exception to this is exception_ignore_args, which was temporally not close to nearby members, and as such I placed it further up to close a hole. On 64-bit Linux this gives us the following shrinks: * zend_op_array: 248 -> 240 * zend_ssa_var: 56 -> 48 * zend_ssa_var_info: 48 -> 40 * php_core_globals: 672 -> 608 * zend_executor_globals: 1824 -> 1792 On 32-bit, the sizes will either remain the same or will result in smaller shrinks. --- Zend/Optimizer/zend_ssa.h | 18 +++++++++--------- Zend/zend_compile.h | 6 +++--- Zend/zend_execute.c | 2 +- Zend/zend_globals.h | 20 +++++++++++--------- main/php_globals.h | 40 ++++++++++++++++++++------------------- 5 files changed, 45 insertions(+), 41 deletions(-) diff --git a/Zend/Optimizer/zend_ssa.h b/Zend/Optimizer/zend_ssa.h index ce33a3732fee8..da1a17469a535 100644 --- a/Zend/Optimizer/zend_ssa.h +++ b/Zend/Optimizer/zend_ssa.h @@ -110,8 +110,8 @@ typedef struct _zend_ssa_var { int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */ int scc; /* strongly connected component */ int definition; /* opcode that defines this value */ - zend_ssa_phi *definition_phi; /* phi that defines this value */ int use_chain; /* uses of this value, linked through opN_use_chain */ + zend_ssa_phi *definition_phi; /* phi that defines this value */ zend_ssa_phi *phi_use_chain; /* uses of this value in Phi, linked through use_chain */ zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constraints */ unsigned int no_val : 1; /* value doesn't matter (used as op1 in ZEND_ASSIGN) */ @@ -122,16 +122,16 @@ typedef struct _zend_ssa_var { typedef struct _zend_ssa_var_info { uint32_t type; /* inferred type (see zend_inference.h) */ + unsigned char has_range : 1; + unsigned char is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */ + unsigned char recursive : 1; + unsigned char use_as_double : 1; + unsigned char delayed_fetch_this : 1; + unsigned char avoid_refcounting : 1; + unsigned char guarded_reference : 1; + unsigned char indirect_reference : 1; /* IS_INDIRECT returned by FETCH_DIM_W/FETCH_OBJ_W */ zend_ssa_range range; zend_class_entry *ce; - unsigned int has_range : 1; - unsigned int is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */ - unsigned int recursive : 1; - unsigned int use_as_double : 1; - unsigned int delayed_fetch_this : 1; - unsigned int avoid_refcounting : 1; - unsigned int guarded_reference : 1; - unsigned int indirect_reference : 1; /* IS_INDIRECT returned by FETCH_DIM_W/FETCH_OBJ_W */ } zend_ssa_var_info; typedef struct _zend_ssa { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8ff8ab0f509fb..3631777ec7f50 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -451,8 +451,8 @@ struct _zend_op_array { uint32_t required_num_args; zend_arg_info *arg_info; HashTable *attributes; - uint32_t T; /* number of temporary variables */ ZEND_MAP_PTR_DEF(void **, run_time_cache); + uint32_t T; /* number of temporary variables */ /* END of common elements */ int cache_size; /* number of run_time_cache_slots * sizeof(void*) */ @@ -506,8 +506,8 @@ typedef struct _zend_internal_function { uint32_t required_num_args; zend_internal_arg_info *arg_info; HashTable *attributes; - uint32_t T; /* number of temporary variables */ ZEND_MAP_PTR_DEF(void **, run_time_cache); + uint32_t T; /* number of temporary variables */ /* END of common elements */ zif_handler handler; @@ -532,8 +532,8 @@ union _zend_function { uint32_t required_num_args; zend_arg_info *arg_info; /* index -1 represents the return value info, if any */ HashTable *attributes; - uint32_t T; /* number of temporary variables */ ZEND_MAP_PTR_DEF(void **, run_time_cache); + uint32_t T; /* number of temporary variables */ } common; zend_op_array op_array; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index d7d41937867c9..efff6cfb4b5bd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -145,8 +145,8 @@ ZEND_API const zend_internal_function zend_pass_function = { 0, /* required_num_args */ (zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */ NULL, /* attributes */ - 0, /* T */ NULL, /* run_time_cache */ + 0, /* T */ ZEND_FN(pass), /* handler */ NULL, /* module */ {NULL,NULL,NULL,NULL} /* reserved */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 71f1f8168ba7c..8900a5f416f53 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -193,22 +193,24 @@ struct _zend_executor_globals { uint32_t jit_trace_num; /* Used by tracing JIT to reference the currently running trace */ - zend_long precision; - int ticks_count; + zend_long precision; + uint32_t persistent_constants_count; uint32_t persistent_functions_count; uint32_t persistent_classes_count; - HashTable *in_autoload; - bool full_tables_cleanup; - /* for extended information support */ bool no_extensions; + bool full_tables_cleanup; + zend_atomic_bool vm_interrupt; zend_atomic_bool timed_out; + + HashTable *in_autoload; + zend_long hard_timeout; void *stack_base; void *stack_limit; @@ -221,20 +223,21 @@ struct _zend_executor_globals { HashTable persistent_list; int user_error_handler_error_reporting; + bool exception_ignore_args; zval user_error_handler; zval user_exception_handler; zend_stack user_error_handlers_error_reporting; zend_stack user_error_handlers; zend_stack user_exception_handlers; - zend_error_handling_t error_handling; zend_class_entry *exception_class; + zend_error_handling_t error_handling; + + int capture_warnings_during_sccp; /* timeout support */ zend_long timeout_seconds; - int capture_warnings_during_sccp; - HashTable *ini_directives; HashTable *modified_ini_directives; zend_ini_entry *error_reporting_ini_entry; @@ -266,7 +269,6 @@ struct _zend_executor_globals { HashTable weakrefs; - bool exception_ignore_args; zend_long exception_string_param_max_len; zend_get_gc_buffer get_gc_buffer; diff --git a/main/php_globals.h b/main/php_globals.h index d5e372cf2b408..d62516f9d6833 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -53,12 +53,19 @@ typedef struct _arg_separators { } arg_separators; struct _php_core_globals { - bool implicit_flush; - zend_long output_buffering; + bool implicit_flush; + bool enable_dl; + uint8_t display_errors; + bool display_startup_errors; + bool log_errors; + bool ignore_repeated_errors; + bool ignore_repeated_source; + bool report_memleaks; + char *output_handler; char *unserialize_callback_func; @@ -67,12 +74,6 @@ struct _php_core_globals { zend_long memory_limit; zend_long max_input_time; - uint8_t display_errors; - bool display_startup_errors; - bool log_errors; - bool ignore_repeated_errors; - bool ignore_repeated_source; - bool report_memleaks; char *error_log; char *doc_root; @@ -116,12 +117,12 @@ struct _php_core_globals { bool register_argc_argv; bool auto_globals_jit; - char *docref_root; - char *docref_ext; - bool html_errors; bool xmlrpc_errors; + char *docref_root; + char *docref_ext; + zend_long xmlrpc_error_number; bool activated_auto_globals[8]; @@ -134,39 +135,40 @@ struct _php_core_globals { bool report_zend_debug; int last_error_type; + int last_error_lineno; zend_string *last_error_message; zend_string *last_error_file; - int last_error_lineno; char *php_sys_temp_dir; char *disable_classes; - bool allow_url_include; -#ifdef PHP_WIN32 - bool com_initialized; -#endif zend_long max_input_nesting_level; zend_long max_input_vars; - bool in_user_include; char *user_ini_filename; zend_long user_ini_cache_ttl; char *request_order; + char *mail_log; bool mail_x_header; bool mail_mixed_lf_and_crlf; - char *mail_log; bool in_error_log; + bool allow_url_include; +#ifdef PHP_WIN32 + bool com_initialized; +#endif + bool in_user_include; + #ifdef PHP_WIN32 bool windows_show_crt_warning; #endif + bool have_called_openlog; zend_long syslog_facility; char *syslog_ident; - bool have_called_openlog; zend_long syslog_filter; zend_long error_log_mode; }; From 23901a7c8011bbbea225017c5eaa632dac820643 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:43:29 +0100 Subject: [PATCH 2/3] Use bool instead of unsigned char for bitfield --- Zend/Optimizer/zend_ssa.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Zend/Optimizer/zend_ssa.h b/Zend/Optimizer/zend_ssa.h index da1a17469a535..1867653184858 100644 --- a/Zend/Optimizer/zend_ssa.h +++ b/Zend/Optimizer/zend_ssa.h @@ -122,14 +122,14 @@ typedef struct _zend_ssa_var { typedef struct _zend_ssa_var_info { uint32_t type; /* inferred type (see zend_inference.h) */ - unsigned char has_range : 1; - unsigned char is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */ - unsigned char recursive : 1; - unsigned char use_as_double : 1; - unsigned char delayed_fetch_this : 1; - unsigned char avoid_refcounting : 1; - unsigned char guarded_reference : 1; - unsigned char indirect_reference : 1; /* IS_INDIRECT returned by FETCH_DIM_W/FETCH_OBJ_W */ + bool has_range : 1; + bool is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */ + bool recursive : 1; + bool use_as_double : 1; + bool delayed_fetch_this : 1; + bool avoid_refcounting : 1; + bool guarded_reference : 1; + bool indirect_reference : 1; /* IS_INDIRECT returned by FETCH_DIM_W/FETCH_OBJ_W */ zend_ssa_range range; zend_class_entry *ce; } zend_ssa_var_info; From 6e0e288ab071fdb1b2f0bf6559dd9482da805397 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 20 Mar 2023 20:43:35 +0100 Subject: [PATCH 3/3] Update UPGRADING.INTERNALS --- UPGRADING.INTERNALS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 487a2ac147e00..4ec7cc5271191 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -39,6 +39,9 @@ PHP 8.3 INTERNALS UPGRADE NOTES - zend_fiber_init_context() * The fast_add_function() has been removed, use add_function() that will call the static inline add_function_fast() instead. +* The order of members of zend_op_array, zend_ssa_var, zend_ssa_var_info, + zend_executor_globals and php_core_globals have changed to improve + struct packing which reduces their size. ======================== 2. Build system changes