diff options
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r-- | Zend/zend_execute_API.c | 101 |
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; } |