From a2e83346134c7a197492cb520ad440e0e1aff463 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 1 Oct 2018 19:05:31 +0300 Subject: [PATCH] Allocate only necessary space for static properties of internal classes in ZTS mode. --- Zend/zend.c | 14 ++++++++++++-- Zend/zend.h | 7 ++++++- Zend/zend_API.c | 10 ++++++++++ Zend/zend_API.h | 2 +- Zend/zend_compile.c | 12 ------------ Zend/zend_execute_API.c | 3 +++ Zend/zend_globals.h | 2 +- Zend/zend_inheritance.c | 10 ++++++++++ Zend/zend_object_handlers.c | 2 +- Zend/zend_opcode.c | 2 +- 10 files changed, 45 insertions(+), 19 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index fe7ea7af2226b..cbbe08858de3d 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -41,6 +41,7 @@ static HashTable *global_class_table = NULL; static HashTable *global_constants_table = NULL; static HashTable *global_auto_globals_table = NULL; static HashTable *global_persistent_list = NULL; +static zend_uintptr_t global_last_static_member = 0; ZEND_TSRMLS_CACHE_DEFINE() # define GLOBAL_FUNCTION_TABLE global_function_table # define GLOBAL_CLASS_TABLE global_class_table @@ -630,9 +631,9 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{ zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, auto_global_dtor, 1, 0); zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, auto_global_copy_ctor); - compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table); + compiler_globals->last_static_member = global_last_static_member; if (compiler_globals->last_static_member) { - compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval*)); + compiler_globals->static_members_table = calloc(compiler_globals->last_static_member + 1, sizeof(zval*)); } else { compiler_globals->static_members_table = NULL; } @@ -935,6 +936,7 @@ int zend_post_startup(void) /* {{{ */ *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; + global_last_static_member = compiler_globals->last_static_member; short_tags_default = CG(short_tags); compiler_options_default = CG(compiler_options); @@ -1083,6 +1085,14 @@ ZEND_API void zend_activate(void) /* {{{ */ } /* }}} */ +#ifdef ZTS +void zend_reset_internal_classes(void) /* {{{ */ +{ + CG(last_static_member) = global_last_static_member; +} +/* }}} */ +#endif + void zend_call_destructors(void) /* {{{ */ { zend_try { diff --git a/Zend/zend.h b/Zend/zend.h index 5ab9fdb532dbb..d6d427ccdbed4 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -127,7 +127,10 @@ struct _zend_class_entry { int default_static_members_count; zval *default_properties_table; zval *default_static_members_table; - zval *static_members_table; + union { + zval *static_members_table; + zend_uintptr_t static_members_table_idx; + }; HashTable function_table; HashTable properties_info; HashTable constants_table; @@ -268,6 +271,8 @@ ZEND_API void zend_activate_modules(void); ZEND_API void zend_deactivate_modules(void); ZEND_API void zend_post_deactivate_modules(void); +void zend_reset_internal_classes(void); + ZEND_API void free_estring(char **str_p); END_EXTERN_C() diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 8c6113c0e15cc..81a4ee76986dc 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3698,6 +3698,16 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property); if (ce->type == ZEND_USER_CLASS) { ce->static_members_table = ce->default_static_members_table; +#ifdef ZTS + } else if (!ce->static_members_table_idx) { + CG(last_static_member)++; + ce->static_members_table_idx = CG(last_static_member); + if (CG(static_members_table)) { + /* Support for run-time declaration: dl() */ + CG(static_members_table) = realloc(CG(static_members_table), (CG(last_static_member) + 1) * sizeof(zval*)); + CG(static_members_table)[ce->static_members_table_idx] = NULL; + } +#endif } } else { if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL && diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 718f5a7a80f35..54344fe0aae9c 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -229,7 +229,7 @@ typedef struct _zend_fcall_info_cache { INIT_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions) #ifdef ZTS -# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members_table:CG(static_members_table)[(zend_intptr_t)(ce)->static_members_table]) +# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members_table:CG(static_members_table)[(ce)->static_members_table_idx]) #else # define CE_STATIC_MEMBERS(ce) ((ce)->static_members_table) #endif diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 504dd536caad8..b96c6c79aac1d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1615,19 +1615,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); if (ce->type == ZEND_INTERNAL_CLASS) { -#ifdef ZTS - int n = zend_hash_num_elements(CG(class_table)); - - if (CG(static_members_table) && n >= CG(last_static_member)) { - /* Support for run-time declaration: dl() */ - CG(last_static_member) = n+1; - CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*)); - CG(static_members_table)[n] = NULL; - } - ce->static_members_table = (zval*)(zend_intptr_t)n; -#else ce->static_members_table = NULL; -#endif } else { ce->static_members_table = ce->default_static_members_table; ce->info.user.doc_comment = NULL; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8d1c056c635ba..2ade3e381865b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -318,6 +318,9 @@ void shutdown_executor(void) /* {{{ */ zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full); zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full); zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full); +#ifdef ZTS + zend_reset_internal_classes(); +#endif } else { ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { zend_constant *c = Z_PTR_P(zv); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 3c92a8f7f61ef..9412801c1b02c 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -119,7 +119,7 @@ struct _zend_compiler_globals { #ifdef ZTS zval **static_members_table; - int last_static_member; + zend_uintptr_t last_static_member; #endif }; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index bb18fbc9fe9a3..816d67e851488 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -928,6 +928,16 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent ce->default_static_members_count += parent_ce->default_static_members_count; if (ce->type == ZEND_USER_CLASS) { ce->static_members_table = ce->default_static_members_table; +#ifdef ZTS + } else if (!ce->static_members_table_idx) { + CG(last_static_member)++; + ce->static_members_table_idx = CG(last_static_member); + if (CG(static_members_table)) { + /* Support for run-time declaration: dl() */ + CG(static_members_table) = realloc(CG(static_members_table), (CG(last_static_member) + 1) * sizeof(zval*)); + CG(static_members_table)[ce->static_members_table_idx] = NULL; + } +#endif } } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 8703cc44dce8d..f56913cbe8302 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1355,7 +1355,7 @@ static void zend_intenal_class_init_statics(zend_class_entry *class_type) /* {{{ } #if ZTS - CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count); + CG(static_members_table)[class_type->static_members_table_idx] = emalloc(sizeof(zval) * class_type->default_static_members_count); #else class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count); #endif diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 64a49b57f1bc3..58d23e6773165 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -146,7 +146,7 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce) zval *end = p + ce->default_static_members_count; #ifdef ZTS - CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; + CG(static_members_table)[ce->static_members_table_idx] = NULL; #else ce->static_members_table = NULL; #endif