summaryrefslogtreecommitdiff
path: root/Zend/zend_execute_API.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r--Zend/zend_execute_API.c136
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);