summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_compile.h3
-rw-r--r--Zend/zend_inheritance.c41
-rw-r--r--Zend/zend_opcode.c33
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c2
4 files changed, 54 insertions, 25 deletions
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