]> granicus.if.org Git - php/commitdiff
Allocate copies of internal functions inherited in user classes at CG(arena), instead...
authorDmitry Stogov <dmitry@zend.com>
Tue, 23 Sep 2014 08:35:42 +0000 (12:35 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 23 Sep 2014 08:35:42 +0000 (12:35 +0400)
Zend/zend_compile.h
Zend/zend_inheritance.c
Zend/zend_opcode.c
ext/opcache/zend_accelerator_util_funcs.c

index 333be9cc528e159f44b5f5b962748202616c8572..573f1fe5ec0ed30b58c12a54a2ae5e5a4611391e 100644 (file)
@@ -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);
index 5cc970ee92cda27861a63f0718c62921ef111359..f240ed71592a6cde49490534d360a112a2ba069b 100644 (file)
@@ -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();
index d57721e58b5e04dd4a2e669b921e11af4f252fb1..3397ed28e24a65993a4ae1451306052ef72edf90 100644 (file)
@@ -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);
+               }
        }
 }
 
index 5dbb48237d377f368757c05a0d0d8b05c88e3889..59977717f788604df2b4987279363808ff19b7bc 100644 (file)
@@ -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