From: Dmitry Stogov Date: Tue, 23 Sep 2014 08:35:42 +0000 (+0400) Subject: Allocate copies of internal functions inherited in user classes at CG(arena), instead... X-Git-Tag: PRE_NATIVE_TLS_MERGE~158^2~53 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7cef08c5d1218544a8d731516fd1bd1272be7e7c;p=php Allocate copies of internal functions inherited in user classes at CG(arena), instead of permanent heap (malloc). --- diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 333be9cc52..573f1fe5ec 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -223,6 +223,9 @@ typedef struct _zend_try_catch_element { /* op_array has finally blocks */ #define ZEND_ACC_HAS_FINALLY_BLOCK 0x20000000 +/* internal function is allocated at arena */ +#define ZEND_ACC_ARENA_ALLOCATED 0x20000000 + #define ZEND_CE_IS_TRAIT(ce) (((ce)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) char *zend_visibility_string(uint32_t fn_flags); diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 5cc970ee92..f240ed7159 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -119,8 +119,14 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ if ((function = zend_hash_str_find_ptr(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) != NULL) { /* inherit parent's constructor */ if (function->type == ZEND_INTERNAL_FUNCTION) { - new_function = pemalloc(sizeof(zend_internal_function), 1); - memcpy(new_function, function, sizeof(zend_internal_function)); + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } } else { new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, function, sizeof(zend_op_array)); @@ -141,8 +147,19 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ (function = zend_hash_find_ptr(&ce->parent->function_table, lc_parent_class_name)) != NULL) { if (function->common.fn_flags & ZEND_ACC_CTOR) { /* inherit parent's constructor */ - new_function = pemalloc(sizeof(zend_function), function->type == ZEND_INTERNAL_FUNCTION); - memcpy(new_function, function, sizeof(zend_function)); + if (function->type == ZEND_INTERNAL_FUNCTION) { + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); + memcpy(new_function, function, sizeof(zend_op_array)); + } zend_hash_update_ptr(&ce->function_table, lc_parent_class_name, new_function); function_add_ref(new_function); } @@ -170,13 +187,19 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */ } /* }}} */ -static zend_function *do_inherit_method(zend_function *old_function TSRMLS_DC) /* {{{ */ +static zend_function *do_inherit_method(zend_function *old_function, zend_class_entry *ce TSRMLS_DC) /* {{{ */ { zend_function *new_function; if (old_function->type == ZEND_INTERNAL_FUNCTION) { - new_function = pemalloc(sizeof(zend_internal_function), 1); - memcpy(new_function, old_function, sizeof(zend_internal_function)); + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, old_function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, old_function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } } else { new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, old_function, sizeof(zend_op_array)); @@ -796,7 +819,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { if (do_inherit_method_check(&ce->function_table, func, key, ce)) { - zend_function *new_func = do_inherit_method(func TSRMLS_CC); + zend_function *new_func = do_inherit_method(func, ce TSRMLS_CC); zend_hash_add_new_ptr(&ce->function_table, key, new_func); } } ZEND_HASH_FOREACH_END(); @@ -884,7 +907,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { if (do_inherit_method_check(&ce->function_table, func, key, ce)) { - zend_function *new_func = do_inherit_method(func TSRMLS_CC); + zend_function *new_func = do_inherit_method(func, ce TSRMLS_CC); zend_hash_add_new_ptr(&ce->function_table, key, new_func); } } ZEND_HASH_FOREACH_END(); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d57721e58b..3397ed28e2 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -100,16 +100,12 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC) { - switch (function->type) { - case ZEND_USER_FUNCTION: - destroy_op_array((zend_op_array *) function TSRMLS_CC); - break; - case ZEND_INTERNAL_FUNCTION: - if (function->common.function_name) { - zend_string_release(function->common.function_name); - } - /* do nothing */ - break; + if (function->type == ZEND_USER_FUNCTION) { + destroy_op_array(&function->op_array TSRMLS_CC); + } else { + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); } } @@ -118,11 +114,18 @@ ZEND_API void zend_function_dtor(zval *zv) zend_function *function = Z_PTR_P(zv); TSRMLS_FETCH(); - destroy_zend_function(function TSRMLS_CC); - if (function->type == ZEND_INTERNAL_FUNCTION) { - pefree(function, 1); - } else if (!function->common.function_name) { - efree_size(function, sizeof(zend_op_array)); + if (function->type == ZEND_USER_FUNCTION) { + ZEND_ASSERT(function->common.function_name); + destroy_op_array(&function->op_array TSRMLS_CC); + /* op_arrays are allocated on arena, so we don't have to free them */ +//??? efree_size(function, sizeof(zend_op_array)); + } else { + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); + if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) { + pefree(function, 1); + } } } diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 5dbb48237d..59977717f7 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -75,7 +75,7 @@ zend_persistent_script* create_persistent_script(void) zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script)); memset(persistent_script, 0, sizeof(zend_persistent_script)); - zend_hash_init(&persistent_script->function_table, 128, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0); + zend_hash_init(&persistent_script->function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0); /* class_table is usually destroyed by free_persistent_script() that * overrides destructor. ZEND_CLASS_DTOR may be used by standard * PHP compiler