diff options
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r-- | Zend/zend_execute_API.c | 136 |
1 files changed, 61 insertions, 75 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index a551449e79..646f3b927b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -205,7 +205,7 @@ static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */ if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC); + i_zval_ptr_dtor(zv); } /* }}} */ @@ -265,6 +265,16 @@ void shutdown_executor(void) /* {{{ */ zend_close_rsrc_list(&EG(regular_list)); } zend_end_try(); + if (!fast_shutdown) { + zend_hash_graceful_reverse_destroy(&EG(symbol_table)); + +#if ZEND_DEBUG + if (gc_enabled() && !CG(unclean_shutdown)) { + gc_collect_cycles(); + } +#endif + } + zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown); /* All resources and objects are destroyed. */ @@ -286,14 +296,6 @@ void shutdown_executor(void) /* {{{ */ zend_hash_discard(EG(class_table), EG(persistent_classes_count)); zend_cleanup_internal_classes(); } else { - zend_hash_graceful_reverse_destroy(&EG(symbol_table)); - -#if ZEND_DEBUG - if (gc_enabled() && !CG(unclean_shutdown)) { - gc_collect_cycles(); - } -#endif - /* remove error handlers before destroying classes and functions, * so that if handler used some class, crash would not happen */ if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { @@ -319,7 +321,7 @@ void shutdown_executor(void) /* {{{ */ } else { ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { zend_constant *c = Z_PTR_P(zv); - if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) { + if (_idx == EG(persistent_constants_count)) { break; } zval_ptr_dtor_nogc(&c->value); @@ -329,22 +331,65 @@ void shutdown_executor(void) /* {{{ */ efree(c); zend_string_release_ex(key, 0); } ZEND_HASH_FOREACH_END_DEL(); + ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) { zend_function *func = Z_PTR_P(zv); - if (func->type == ZEND_INTERNAL_FUNCTION) { + if (_idx == EG(persistent_functions_count)) { break; } destroy_op_array(&func->op_array); zend_string_release_ex(key, 0); } ZEND_HASH_FOREACH_END_DEL(); + + /* Cleanup preloaded immutable functions */ + ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) { + zend_op_array *op_array = Z_PTR_P(zv); + if (op_array->type == ZEND_INTERNAL_FUNCTION) { + break; + } + ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_IMMUTABLE); + if (op_array->static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); + if (ht) { + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + zend_array_destroy(ht); + } + } + } ZEND_HASH_FOREACH_END(); + ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { - zend_class_entry *ce = Z_PTR_P(zv); - if (ce->type == ZEND_INTERNAL_CLASS) { + if (_idx == EG(persistent_classes_count)) { break; } destroy_zend_class(zv); zend_string_release_ex(key, 0); } ZEND_HASH_FOREACH_END_DEL(); + + /* Cleanup preloaded immutable classes */ + ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { + zend_class_entry *ce = Z_PTR_P(zv); + if (ce->type == ZEND_INTERNAL_CLASS) { + break; + } + ZEND_ASSERT(ce->ce_flags & ZEND_ACC_IMMUTABLE); + if (ce->default_static_members_count) { + zend_cleanup_internal_class_data(ce); + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { + zend_op_array *op_array; + ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + if (op_array->type == ZEND_USER_FUNCTION) { + if (op_array->static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); + if (ht) { + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + zend_array_destroy(ht); + } + } + } + } ZEND_HASH_FOREACH_END(); + } + } ZEND_HASH_FOREACH_END(); } zend_cleanup_internal_classes(); @@ -828,7 +873,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } /* }}} */ -ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */ +ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, int use_autoload) /* {{{ */ { zend_class_entry *ce = NULL; zval args[1], *zv; @@ -838,7 +883,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k zend_fcall_info_cache fcall_cache; if (key) { - lc_name = Z_STR_P(key); + lc_name = key; } else { if (name == NULL || !ZSTR_LEN(name)) { return NULL; @@ -1352,7 +1397,7 @@ check_fetch_type: } /* }}} */ -zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type) /* {{{ */ +zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, int fetch_type) /* {{{ */ { zend_class_entry *ce; @@ -1374,65 +1419,6 @@ zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval * } /* }}} */ -#define MAX_ABSTRACT_INFO_CNT 3 -#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" -#define DISPLAY_ABSTRACT_FN(idx) \ - ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ - ai.afn[idx] ? "::" : "", \ - ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \ - ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "") - -typedef struct _zend_abstract_info { - zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1]; - int cnt; - int ctor; -} zend_abstract_info; - -static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */ -{ - if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { - if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { - ai->afn[ai->cnt] = fn; - } - if (fn->common.fn_flags & ZEND_ACC_CTOR) { - if (!ai->ctor) { - ai->cnt++; - ai->ctor = 1; - } else { - ai->afn[ai->cnt] = NULL; - } - } else { - ai->cnt++; - } - } -} -/* }}} */ - -void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */ -{ - zend_function *func; - zend_abstract_info ai; - - if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - memset(&ai, 0, sizeof(ai)); - - ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { - zend_verify_abstract_class_function(func, &ai); - } ZEND_HASH_FOREACH_END(); - - if (ai.cnt) { - zend_error_noreturn(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", - ZSTR_VAL(ce->name), ai.cnt, - ai.cnt > 1 ? "s" : "", - DISPLAY_ABSTRACT_FN(0), - DISPLAY_ABSTRACT_FN(1), - DISPLAY_ABSTRACT_FN(2) - ); - } - } -} -/* }}} */ - ZEND_API int zend_delete_global_variable(zend_string *name) /* {{{ */ { return zend_hash_del_ind(&EG(symbol_table), name); |