From 5371206da43f102ece15b8670ba00c2551a7027a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 3 Oct 2018 17:12:19 +0200 Subject: [PATCH 1/2] Implement mechanism for finding prop_info for property slot Currently there is no efficient way of finding the property_info which corresponds to a given property slot. This patch implements such a mechanism, by storing an array of property_infos in offset order on the class. This structure is lazily initialized when it is needed, though we could also compute it during inheritance. This patch only uses it to optimize visibility checks during foreach (and get_object_vars etc). We avoid having to look up the property by name and can directly check the accessibility. We're also interested in having this mapping to handle some edge cases in the typed properties implementation. --- Zend/zend.h | 2 ++ Zend/zend_builtin_functions.c | 3 +- Zend/zend_compile.c | 1 + Zend/zend_object_handlers.c | 59 +++++++++++++++++++++++++++++++++++ Zend/zend_object_handlers.h | 26 +++++++++++++++ Zend/zend_opcode.c | 7 +++++ Zend/zend_vm_def.h | 4 +-- Zend/zend_vm_execute.h | 4 +-- ext/standard/http.c | 28 ++++++++++------- 9 files changed, 116 insertions(+), 18 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index d6d427ccdbed4..fb4f8dc8f8293 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -135,6 +135,8 @@ struct _zend_class_entry { HashTable properties_info; HashTable constants_table; + struct _zend_property_info **properties_info_table; + zend_function *constructor; zend_function *destructor; zend_function *clone; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 364d478ab73f3..dc8d0c3dde9fc 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1198,8 +1198,7 @@ ZEND_FUNCTION(get_object_vars) continue; } - ZEND_ASSERT(key); - if (zend_check_property_access(zobj, key) == FAILURE) { + if (zend_check_property_slot_access(zobj, value) == FAILURE) { continue; } unmangle = 1; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index daaf00c9b1386..bf8295db2364d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1622,6 +1622,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->default_properties_count = 0; ce->default_static_members_count = 0; + ce->properties_info_table = NULL; if (nullify_handlers) { ce->constructor = NULL; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 6773f99704347..2614569ac568a 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -58,6 +58,39 @@ called, we cal __call handler. */ +ZEND_API zend_property_info **zend_build_properties_info_table(zend_class_entry *ce) +{ + zend_property_info *prop; + zend_property_info **table = pemalloc( + sizeof(zend_property_info *) * ce->default_properties_count, + ce->type == ZEND_INTERNAL_CLASS + ); + + ZEND_ASSERT(ce->properties_info_table == NULL); + ZEND_ASSERT(ce->default_properties_count != 0); + ce->properties_info_table = table; + + if (ce->parent && ce->parent->default_properties_count != 0) { + zend_property_info **parent_table = zend_get_properties_info_table(ce->parent); + memcpy( + table, parent_table, + sizeof(zend_property_info *) * ce->parent->default_properties_count + ); + + /* Child did not add any new properties, we are done */ + if (ce->default_properties_count == ce->parent->default_properties_count) { + return table; + } + } + + ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) { + table[OBJ_PROP_TO_NUM(prop->offset)] = prop; + } + } ZEND_HASH_FOREACH_END(); + return table; +} + ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ { if (!zobj->properties) { @@ -571,6 +604,32 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf } /* }}} */ +ZEND_API int zend_check_property_info_access(zend_property_info *prop_info) /* {{{ */ +{ + zend_class_entry *scope; + if (prop_info->flags & ZEND_ACC_PUBLIC) { + return SUCCESS; + } + + if (UNEXPECTED(EG(fake_scope))) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + + if (prop_info->ce == scope) { + return SUCCESS; + } + + if ((prop_info->flags & ZEND_ACC_PROTECTED) + && is_protected_compatible_scope(prop_info->ce, scope)) { + return SUCCESS; + } + + return FAILURE; +} +/* }}} */ + static void zend_property_guard_dtor(zval *el) /* {{{ */ { uint32_t *ptr = (uint32_t*)Z_PTR_P(el); if (EXPECTED(!(((zend_uintptr_t)ptr) & 1))) { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 3d89783727b29..4dae22de92d6c 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -242,6 +242,32 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose } \ } while (0) +ZEND_API struct _zend_property_info **zend_build_properties_info_table(zend_class_entry *ce); +ZEND_API int zend_check_property_info_access(struct _zend_property_info *prop_info); + +static inline struct _zend_property_info **zend_get_properties_info_table(zend_class_entry *ce) +{ + ZEND_ASSERT(ce->default_properties_count != 0); + if (ce->properties_info_table) { + return ce->properties_info_table; + } + + return zend_build_properties_info_table(ce); +} + +static inline struct _zend_property_info *zend_get_property_info_for_slot(zend_object *obj, zval *slot) +{ + struct _zend_property_info **table = zend_get_properties_info_table(obj->ce); + intptr_t prop_num = slot - obj->properties_table; + ZEND_ASSERT(prop_num >= 0 && prop_num < obj->ce->default_properties_count); + return table[prop_num]; +} + +static inline int zend_check_property_slot_access(zend_object *obj, zval *slot) /* {{{ */ +{ + return zend_check_property_info_access(zend_get_property_info_for_slot(obj, slot)); +} + #define zend_free_trampoline(func) do { \ if ((func) == &EG(trampoline)) { \ EG(trampoline).common.function_name = NULL; \ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index f348b0b5892e3..8f5690696e576 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -284,6 +284,10 @@ ZEND_API void destroy_zend_class(zval *zv) _destroy_zend_class_traits_info(ce); } + if (ce->properties_info_table) { + efree(ce->properties_info_table); + } + break; case ZEND_INTERNAL_CLASS: if (ce->default_properties_table) { @@ -339,6 +343,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->num_interfaces > 0) { free(ce->interfaces); } + if (ce->properties_info_table) { + free(ce->properties_info_table); + } free(ce); break; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 36fb9a1779b4c..8ee520527dc9d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5876,7 +5876,7 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit): value = Z_INDIRECT_P(value); value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + && EXPECTED(zend_check_property_slot_access(Z_OBJ_P(array), value) == SUCCESS)) { break; } } else { @@ -6026,7 +6026,7 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) value = Z_INDIRECT_P(value); value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + && EXPECTED(zend_check_property_slot_access(Z_OBJ_P(array), value) == SUCCESS)) { break; } } else { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 03d767247b662..ebb852f603a22 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -21352,7 +21352,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZE value = Z_INDIRECT_P(value); value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + && EXPECTED(zend_check_property_slot_access(Z_OBJ_P(array), value) == SUCCESS)) { break; } } else { @@ -21502,7 +21502,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z value = Z_INDIRECT_P(value); value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF) - && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) { + && EXPECTED(zend_check_property_slot_access(Z_OBJ_P(array), value) == SUCCESS)) { break; } } else { diff --git a/ext/standard/http.c b/ext/standard/http.c index 293258b1aafc1..08729f8a9ad89 100644 --- a/ext/standard/http.c +++ b/ext/standard/http.c @@ -53,25 +53,29 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, } arg_sep_len = strlen(arg_sep); - ZEND_HASH_FOREACH_KEY_VAL_IND(ht, idx, key, zdata) { - /* handling for private & protected object properties */ + ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) { if (key) { - if (ZSTR_VAL(key)[0] == '\0' && type != NULL) { - const char *tmp; + prop_name = ZSTR_VAL(key); + prop_len = ZSTR_LEN(key); + } else { + prop_name = NULL; + prop_len = 0; + } + + if (Z_TYPE_P(zdata) == IS_INDIRECT) { + zdata = Z_INDIRECT_P(zdata); + if (Z_ISUNDEF_P(zdata)) { + continue; + } - zend_object *zobj = Z_OBJ_P(type); - if (zend_check_property_access(zobj, key) != SUCCESS) { + if (type) { + const char *tmp; + if (zend_check_property_slot_access(Z_OBJ_P(type), zdata) != SUCCESS) { /* private or protected property access outside of the class */ continue; } zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); - } else { - prop_name = ZSTR_VAL(key); - prop_len = ZSTR_LEN(key); } - } else { - prop_name = NULL; - prop_len = 0; } ZVAL_DEREF(zdata); From d222bd6c61a4572238467c29612d98b90e39e98d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 7 Oct 2018 18:44:21 +0200 Subject: [PATCH 2/2] Build properties_info_table during compilation And cache it in opcache. --- Zend/zend_API.c | 11 +++++++ Zend/zend_compile.c | 2 ++ Zend/zend_inheritance.c | 38 +++++++++++++++++++++++ Zend/zend_inheritance.h | 1 + Zend/zend_object_handlers.c | 33 -------------------- Zend/zend_object_handlers.h | 13 +------- Zend/zend_opcode.c | 4 --- ext/opcache/zend_accelerator_util_funcs.c | 10 ++++++ ext/opcache/zend_file_cache.c | 22 +++++++++++++ ext/opcache/zend_persist.c | 13 ++++++++ ext/opcache/zend_persist_calc.c | 4 +++ 11 files changed, 102 insertions(+), 49 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 81a4ee76986dc..f9c3cddc79e4e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2743,6 +2743,7 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla if (parent_ce) { zend_do_inheritance(register_class, parent_ce); + zend_build_properties_info_table(register_class); } return register_class; } @@ -3715,10 +3716,20 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z property_info->offset = property_info_ptr->offset; zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]); zend_hash_del(&ce->properties_info, name); + + ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS); + ZEND_ASSERT(ce->properties_info_table != NULL); + ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info; } else { property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count); ce->default_properties_count++; ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS); + + /* For user classes this is handled during linking */ + if (ce->type == ZEND_INTERNAL_CLASS) { + ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1); + ce->properties_info_table[ce->default_properties_count - 1] = property_info; + } } ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bf8295db2364d..481a3bd13f17a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6332,6 +6332,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ CG(zend_lineno) = decl->end_lineno; ce->ce_flags |= ZEND_ACC_LINKED; zend_do_inheritance(ce, parent_ce); + zend_build_properties_info_table(ce); if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { zend_verify_abstract_class(ce); } @@ -6343,6 +6344,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } else { if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { zend_string_release(lcname); + zend_build_properties_info_table(ce); ce->ce_flags |= ZEND_ACC_LINKED; return; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9a4efed9b9e81..378100dc73a2d 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -782,6 +782,42 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa } /* }}} */ +void zend_build_properties_info_table(zend_class_entry *ce) +{ + zend_property_info **table, *prop; + if (ce->default_properties_count == 0) { + return; + } + + ZEND_ASSERT(ce->properties_info_table == NULL); + if (ce->type == ZEND_USER_CLASS) { + ce->properties_info_table = table = zend_arena_alloc(&CG(arena), + sizeof(zend_property_info *) * ce->default_properties_count); + } else { + ce->properties_info_table = table = pemalloc( + sizeof(zend_property_info *) * ce->default_properties_count, 1); + } + + if (ce->parent && ce->parent->default_properties_count != 0) { + zend_property_info **parent_table = ce->parent->properties_info_table; + memcpy( + table, parent_table, + sizeof(zend_property_info *) * ce->parent->default_properties_count + ); + + /* Child did not add any new properties, we are done */ + if (ce->default_properties_count == ce->parent->default_properties_count) { + return; + } + } + + ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) { + table[OBJ_PROP_TO_NUM(prop->offset)] = prop; + } + } ZEND_HASH_FOREACH_END(); +} + ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */ { zend_property_info *property_info; @@ -1936,6 +1972,8 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent) if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { zend_verify_abstract_class(ce); } + + zend_build_properties_info_table(ce); } /* }}} */ diff --git a/Zend/zend_inheritance.h b/Zend/zend_inheritance.h index d6cca74389b3d..fe85aea65022b 100644 --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@ -31,6 +31,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent_ void zend_verify_abstract_class(zend_class_entry *ce); void zend_check_deprecated_constructor(const zend_class_entry *ce); +void zend_build_properties_info_table(zend_class_entry *ce); END_EXTERN_C() diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 2614569ac568a..82959e7fda2ea 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -58,39 +58,6 @@ called, we cal __call handler. */ -ZEND_API zend_property_info **zend_build_properties_info_table(zend_class_entry *ce) -{ - zend_property_info *prop; - zend_property_info **table = pemalloc( - sizeof(zend_property_info *) * ce->default_properties_count, - ce->type == ZEND_INTERNAL_CLASS - ); - - ZEND_ASSERT(ce->properties_info_table == NULL); - ZEND_ASSERT(ce->default_properties_count != 0); - ce->properties_info_table = table; - - if (ce->parent && ce->parent->default_properties_count != 0) { - zend_property_info **parent_table = zend_get_properties_info_table(ce->parent); - memcpy( - table, parent_table, - sizeof(zend_property_info *) * ce->parent->default_properties_count - ); - - /* Child did not add any new properties, we are done */ - if (ce->default_properties_count == ce->parent->default_properties_count) { - return table; - } - } - - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { - if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) { - table[OBJ_PROP_TO_NUM(prop->offset)] = prop; - } - } ZEND_HASH_FOREACH_END(); - return table; -} - ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ { if (!zobj->properties) { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 4dae22de92d6c..b43279ae932ec 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -242,22 +242,11 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose } \ } while (0) -ZEND_API struct _zend_property_info **zend_build_properties_info_table(zend_class_entry *ce); ZEND_API int zend_check_property_info_access(struct _zend_property_info *prop_info); -static inline struct _zend_property_info **zend_get_properties_info_table(zend_class_entry *ce) -{ - ZEND_ASSERT(ce->default_properties_count != 0); - if (ce->properties_info_table) { - return ce->properties_info_table; - } - - return zend_build_properties_info_table(ce); -} - static inline struct _zend_property_info *zend_get_property_info_for_slot(zend_object *obj, zval *slot) { - struct _zend_property_info **table = zend_get_properties_info_table(obj->ce); + struct _zend_property_info **table = obj->ce->properties_info_table; intptr_t prop_num = slot - obj->properties_table; ZEND_ASSERT(prop_num >= 0 && prop_num < obj->ce->default_properties_count); return table[prop_num]; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 8f5690696e576..9f9fee5ce13c1 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -284,10 +284,6 @@ ZEND_API void destroy_zend_class(zval *zv) _destroy_zend_class_traits_info(ce); } - if (ce->properties_info_table) { - efree(ce->properties_info_table); - } - break; case ZEND_INTERNAL_CLASS: if (ce->default_properties_table) { diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 4db2c34fbcd12..7e7350a5b1f65 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -279,6 +279,16 @@ static void zend_class_copy_ctor(zend_class_entry **pce) /* constants table */ zend_hash_clone_constants(&ce->constants_table, &old_ce->constants_table); + if (ce->properties_info_table) { + int i; + ce->properties_info_table = ARENA_REALLOC(ce->properties_info_table); + for (i = 0; i < ce->default_properties_count; i++) { + if (IN_ARENA(ce->properties_info_table[i])) { + ce->properties_info_table[i] = ARENA_REALLOC(ce->properties_info_table[i]); + } + } + } + if (ce->num_interfaces) { zend_class_name *interface_names; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index f6ed2fc91877e..da99c9d55ae78 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -653,6 +653,19 @@ static void zend_file_cache_serialize_class(zval *zv, SERIALIZE_STR(ce->info.user.doc_comment); zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info); + if (ce->properties_info_table) { + uint32_t i; + zend_property_info **table; + + SERIALIZE_PTR(ce->properties_info_table); + table = ce->properties_info_table; + UNSERIALIZE_PTR(table); + + for (i = 0; i < ce->default_properties_count; i++) { + SERIALIZE_PTR(table[i]); + } + } + if (ce->num_interfaces) { uint32_t i; zend_class_name *interface_names; @@ -1294,6 +1307,15 @@ static void zend_file_cache_unserialize_class(zval *zv, zend_file_cache_unserialize_hash(&ce->properties_info, script, buf, zend_file_cache_unserialize_prop_info, NULL); + if (ce->properties_info_table) { + uint32_t i; + UNSERIALIZE_PTR(ce->properties_info_table); + + for (i = 0; i < ce->default_properties_count; i++) { + UNSERIALIZE_PTR(ce->properties_info_table[i]); + } + } + if (ce->num_interfaces) { uint32_t i; diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 6b3413324c62f..67ba23a2adbaa 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -778,6 +778,19 @@ static void zend_persist_class_entry(zval *zv) zend_hash_persist(&ce->properties_info, zend_persist_property_info); HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS); + if (ce->properties_info_table) { + int i; + + size_t size = sizeof(zend_property_info *) * ce->default_properties_count; + memcpy(ZCG(arena_mem), ce->properties_info_table, size); + ce->properties_info_table = ZCG(arena_mem); + ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(size)); + + for (i = 0; i < ce->default_properties_count; i++) { + ce->properties_info_table[i] = zend_shared_alloc_get_xlat_entry(ce->properties_info_table[i]); + } + } + if (ce->num_interfaces) { uint32_t i = 0; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index fcd5db58a7e9d..f60e9495a9dcc 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -343,6 +343,10 @@ static void zend_persist_class_entry_calc(zval *zv) zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc); + if (ce->properties_info_table) { + ADD_ARENA_SIZE(sizeof(zend_property_info *) * ce->default_properties_count); + } + if (ce->num_interfaces) { uint32_t i;