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.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index b55b2e7385..af3c8cc670 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -258,13 +258,13 @@ void shutdown_executor(void) /* {{{ */
zend_string *key;
zval *zv;
#if ZEND_DEBUG
- zend_bool fast_shutdown = 0;
+ bool fast_shutdown = 0;
#else
- zend_bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup);
+ bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup);
#endif
zend_try {
- zend_llist_destroy(&CG(open_files));
+ zend_stream_shutdown();
} zend_end_try();
EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
@@ -278,6 +278,24 @@ void shutdown_executor(void) /* {{{ */
if (!fast_shutdown) {
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
+ /* Constants may contain objects, destroy them before the object store. */
+ if (EG(full_tables_cleanup)) {
+ zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
+ } else {
+ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
+ zend_constant *c = Z_PTR_P(zv);
+ if (_idx == EG(persistent_constants_count)) {
+ break;
+ }
+ zval_ptr_dtor_nogc(&c->value);
+ if (c->name) {
+ zend_string_release_ex(c->name, 0);
+ }
+ efree(c);
+ zend_string_release_ex(key, 0);
+ } ZEND_HASH_FOREACH_END_DEL();
+ }
+
/* Release static properties and static variables prior to the final GC run,
* as they may hold GC roots. */
ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
@@ -285,27 +303,42 @@ void shutdown_executor(void) /* {{{ */
if (op_array->type == ZEND_INTERNAL_FUNCTION) {
break;
}
- if (op_array->static_variables) {
+ if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
if (ht) {
- zend_array_release(ht);
+ zend_array_destroy(ht);
ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
}
}
} ZEND_HASH_FOREACH_END();
ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
zend_class_entry *ce = Z_PTR_P(zv);
+
if (ce->default_static_members_count) {
zend_cleanup_internal_class_data(ce);
}
+
+ if (ZEND_MAP_PTR(ce->mutable_data) && ZEND_MAP_PTR_GET_IMM(ce->mutable_data)) {
+ zend_cleanup_mutable_class_data(ce);
+ } else if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
+ /* Constants may contain objects, destroy the values before the object store. */
+ zend_class_constant *c;
+ ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
+ if (c->ce == ce) {
+ zval_ptr_dtor_nogc(&c->value);
+ ZVAL_UNDEF(&c->value);
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+
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) {
+ if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
if (ht) {
- zend_array_release(ht);
+ zend_array_destroy(ht);
ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
}
}
@@ -334,6 +367,8 @@ void shutdown_executor(void) /* {{{ */
gc_collect_cycles();
}
#endif
+ } else {
+ zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
}
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
@@ -350,7 +385,6 @@ void shutdown_executor(void) /* {{{ */
* Zend Memory Manager frees memory by its own. We don't have to free
* each allocated block separately.
*/
- zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
zend_hash_discard(EG(function_table), EG(persistent_functions_count));
zend_hash_discard(EG(class_table), EG(persistent_classes_count));
zend_cleanup_internal_classes();
@@ -358,23 +392,9 @@ void shutdown_executor(void) /* {{{ */
zend_vm_stack_destroy();
if (EG(full_tables_cleanup)) {
- zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
} else {
- ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
- zend_constant *c = Z_PTR_P(zv);
- if (_idx == EG(persistent_constants_count)) {
- break;
- }
- zval_ptr_dtor_nogc(&c->value);
- if (c->name) {
- zend_string_release_ex(c->name, 0);
- }
- 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 (_idx == EG(persistent_functions_count)) {
@@ -604,13 +624,13 @@ ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */
}
/* }}} */
-ZEND_API zend_bool zend_is_executing(void) /* {{{ */
+ZEND_API bool zend_is_executing(void) /* {{{ */
{
return EG(current_execute_data) != 0;
}
/* }}} */
-ZEND_API zend_result zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
+ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
{
if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
zend_ast *ast = Z_ASTVAL_P(p);
@@ -638,7 +658,7 @@ ZEND_API zend_result zval_update_constant_ex(zval *p, zend_class_entry *scope) /
}
/* }}} */
-ZEND_API zend_result zval_update_constant(zval *pp) /* {{{ */
+ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp) /* {{{ */
{
return zval_update_constant_ex(pp, EG(current_execute_data) ? zend_get_executed_scope() : CG(active_class_entry));
}
@@ -759,7 +779,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
for (i=0; i<fci->param_count; i++) {
zval *param = ZEND_CALL_ARG(call, i+1);
zval *arg = &fci->params[i];
- zend_bool must_wrap = 0;
+ bool must_wrap = 0;
if (UNEXPECTED(Z_ISUNDEF_P(arg))) {
/* Allow forwarding undef slots. This is only used by Closure::__invoke(). */
ZVAL_UNDEF(param);
@@ -806,9 +826,9 @@ cleanup_args:
zend_string *name;
zval *arg;
uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1;
- zend_bool have_named_params = 0;
+ bool have_named_params = 0;
ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) {
- zend_bool must_wrap = 0;
+ bool must_wrap = 0;
zval *target;
if (name) {
void *cache_slot[2] = {NULL, NULL};
@@ -1017,7 +1037,7 @@ static const uint32_t valid_chars[8] = {
0xffffffff,
};
-ZEND_API zend_bool zend_is_valid_class_name(zend_string *name) {
+ZEND_API bool zend_is_valid_class_name(zend_string *name) {
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
unsigned char c = ZSTR_VAL(name)[i];
if (!ZEND_BIT_TEST(valid_chars, c)) {
@@ -1059,7 +1079,15 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
(ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
- ce->ce_flags |= ZEND_ACC_HAS_UNLINKED_USES;
+ if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
+ if (!CG(unlinked_uses)) {
+ ALLOC_HASHTABLE(CG(unlinked_uses));
+ zend_hash_init(CG(unlinked_uses), 0, NULL, NULL, 0);
+ }
+ zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_long)(zend_uintptr_t)ce);
+ } else {
+ ce->ce_flags |= ZEND_ACC_HAS_UNLINKED_USES;
+ }
return ce;
}
return NULL;
@@ -1210,6 +1238,7 @@ ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *re
}
EG(no_extensions)=0;
+ zend_destroy_static_vars(new_op_array);
destroy_op_array(new_op_array);
efree_size(new_op_array, sizeof(zend_op_array));
retval = SUCCESS;
@@ -1494,9 +1523,8 @@ check_fetch_type:
break;
}
- if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
- return zend_lookup_class_ex(class_name, NULL, fetch_type);
- } else if ((ce = zend_lookup_class_ex(class_name, NULL, fetch_type)) == NULL) {
+ ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
+ if (!ce) {
if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
@@ -1514,11 +1542,8 @@ check_fetch_type:
zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, int fetch_type) /* {{{ */
{
- zend_class_entry *ce;
-
- if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
- return zend_lookup_class_ex(class_name, key, fetch_type);
- } else if ((ce = zend_lookup_class_ex(class_name, key, fetch_type)) == NULL) {
+ zend_class_entry *ce = zend_lookup_class_ex(class_name, key, fetch_type);
+ if (!ce) {
if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
return NULL;
}