diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 381220a11468b..71aefe04a821a 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -767,7 +767,7 @@ static inline zend_result ct_eval_in_array(zval *result, uint32_t extended_value zval key_tmp; res = 0; - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { res = 1; diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 83671106c8add..caab99c98b5f7 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -1360,15 +1360,15 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void zend_foreach_op_array_helper(&script->main_op_array, func, context); - ZEND_HASH_FOREACH_PTR(&script->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&script->function_table, op_array) { zend_foreach_op_array_helper(op_array, func, context); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_STR_KEY_PTR(&script->class_table, key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&script->class_table, key, ce) { if (ce->refcount > 1 && !zend_string_equals_ci(key, ce->name)) { continue; } - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->scope == ce && op_array->type == ZEND_USER_FUNCTION && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { @@ -1516,11 +1516,11 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l } } - ZEND_HASH_FOREACH_STR_KEY_PTR(&script->class_table, key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&script->class_table, key, ce) { if (ce->refcount > 1 && !zend_string_equals_ci(key, ce->name)) { continue; } - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) { if (op_array->scope != ce && op_array->type == ZEND_USER_FUNCTION) { zend_op_array *orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, name); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 245967d678883..36265ca9d4ab3 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1284,8 +1284,11 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ zend_string *key; zval *value; + if (HT_IS_PACKED(properties)) { + return; + } EG(fake_scope) = Z_OBJCE_P(obj); - ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, value) { if (key) { write_property(zobj, key, value, NULL); } @@ -1321,7 +1324,7 @@ ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_ zend_hash_init(constants_table, zend_hash_num_elements(&class_type->constants_table), NULL, NULL, 0); zend_hash_extend(constants_table, zend_hash_num_elements(&class_type->constants_table), 0); - ZEND_HASH_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) { if (Z_TYPE(c->value) == IS_CONSTANT_AST) { new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); memcpy(new_c, c, sizeof(zend_class_constant)); @@ -1409,7 +1412,7 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) / } else { constants_table = &class_type->constants_table; } - ZEND_HASH_FOREACH_PTR(constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(constants_table, c) { if (Z_TYPE(c->value) == IS_CONSTANT_AST) { val = &c->value; if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) { @@ -1461,7 +1464,7 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) / } if (class_type->default_static_members_count) { - ZEND_HASH_FOREACH_PTR(&class_type->properties_info, prop_info) { + ZEND_HASH_MAP_FOREACH_PTR(&class_type->properties_info, prop_info) { if (prop_info->flags & ZEND_ACC_STATIC) { val = static_members_table + prop_info->offset; if (Z_TYPE_P(val) == IS_CONSTANT_AST @@ -1526,7 +1529,7 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti zend_string *key; zend_property_info *property_info; - ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) { property_info = zend_get_property_info(object->ce, key, 1); if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info && @@ -2243,7 +2246,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ int class_count = 0; /* Collect extensions with request startup/shutdown handlers */ - ZEND_HASH_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { if (module->request_startup_func) { startup_count++; } @@ -2266,7 +2269,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ module_post_deactivate_handlers[post_deactivate_count] = NULL; startup_count = 0; - ZEND_HASH_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { if (module->request_startup_func) { module_request_startup_handlers[startup_count++] = module; } @@ -2279,7 +2282,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ } ZEND_HASH_FOREACH_END(); /* Collect internal classes with static members */ - ZEND_HASH_FOREACH_PTR(CG(class_table), ce) { + ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) { if (ce->type == ZEND_INTERNAL_CLASS && ce->default_static_members_count > 0) { class_count++; @@ -2292,7 +2295,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ class_cleanup_handlers[class_count] = NULL; if (class_count) { - ZEND_HASH_FOREACH_PTR(CG(class_table), ce) { + ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) { if (ce->type == ZEND_INTERNAL_CLASS && ce->default_static_members_count > 0) { class_cleanup_handlers[--class_count] = ce; @@ -2981,7 +2984,7 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */ if (EG(full_tables_cleanup)) { zend_module_entry *module; - ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&module_registry, module) { if (module->request_shutdown_func) { zend_try { module->request_shutdown_func(module->type, module->module_number); @@ -3009,12 +3012,12 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */ zval *zv; zend_string *key; - ZEND_HASH_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { if (module->post_deactivate_func) { module->post_deactivate_func(); } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) { module = Z_PTR_P(zv); if (module->type != MODULE_TEMPORARY) { break; @@ -3022,7 +3025,7 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */ module_destructor(module); free(module); zend_string_release_ex(key, 0); - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); } else { zend_module_entry **p = module_post_deactivate_handlers; @@ -3267,14 +3270,14 @@ ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_nam INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new); disabled_class->create_object = display_disabled_class; - ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) { + ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->function_table, fn) { if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && fn->common.scope == disabled_class) { zend_free_internal_arg_info(&fn->internal_function); } } ZEND_HASH_FOREACH_END(); zend_hash_clean(&disabled_class->function_table); - ZEND_HASH_FOREACH_PTR(&disabled_class->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->properties_info, prop) { if (prop->ce == disabled_class) { zend_string_release(prop->name); zend_type_release(prop->type, /* persistent */ 1); diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index a9bf3811b3710..28c4a4483637b 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -78,7 +78,7 @@ static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, if (attributes) { zend_attribute *attr; - ZEND_HASH_FOREACH_PTR(attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) { if (attr->offset == offset && zend_string_equals(attr->lcname, lcname)) { return attr; } @@ -93,7 +93,7 @@ static zend_attribute *get_attribute_str(HashTable *attributes, const char *str, if (attributes) { zend_attribute *attr; - ZEND_HASH_FOREACH_PTR(attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) { if (attr->offset == offset && ZSTR_LEN(attr->lcname) == len) { if (0 == memcmp(ZSTR_VAL(attr->lcname), str, len)) { return attr; @@ -173,7 +173,7 @@ ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute * { zend_attribute *other; - ZEND_HASH_FOREACH_PTR(attributes, other) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, other) { if (other != attr && other->offset == attr->offset) { if (zend_string_equals(other->lcname, attr->lcname)) { return 1; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 7e58639508d55..89475235d818e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -669,7 +669,7 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, bool s zend_string *key; zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { if (((prop_info->flags & ZEND_ACC_PROTECTED) && !zend_check_protected(prop_info->ce, scope)) || ((prop_info->flags & ZEND_ACC_PRIVATE) && @@ -758,7 +758,7 @@ ZEND_FUNCTION(get_object_vars) } else { array_init_size(return_value, zend_hash_num_elements(properties)); - ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) { + ZEND_HASH_MAP_FOREACH_KEY_VAL(properties, num_key, key, value) { bool is_dynamic = 1; if (Z_TYPE_P(value) == IS_INDIRECT) { value = Z_INDIRECT_P(value); @@ -838,7 +838,7 @@ ZEND_FUNCTION(get_class_methods) array_init(return_value); scope = zend_get_executed_scope(); - ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) || (scope && (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && @@ -1094,7 +1094,7 @@ ZEND_FUNCTION(get_included_files) ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&EG(included_files), entry) { if (entry) { add_next_index_str(return_value, zend_string_copy(entry)); } @@ -1248,7 +1248,7 @@ static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int fla array_init(return_value); zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { ce = Z_PTR_P(zv); if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags && key @@ -1309,7 +1309,7 @@ ZEND_FUNCTION(get_defined_functions) array_init(&user); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), key, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(function_table), key, func) { if (key && ZSTR_VAL(key)[0] != 0) { if (func->type == ZEND_INTERNAL_FUNCTION) { add_next_index_str(&internal, zend_string_copy(key)); @@ -1455,7 +1455,7 @@ ZEND_FUNCTION(get_loaded_extensions) } else { zend_module_entry *module; - ZEND_HASH_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { add_next_index_string(return_value, module->name); } ZEND_HASH_FOREACH_END(); } @@ -1485,13 +1485,13 @@ ZEND_FUNCTION(get_defined_constants) module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *)); module_names[0] = "internal"; - ZEND_HASH_FOREACH_PTR(&module_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { module_names[module->module_number] = (char *)module->name; i++; } ZEND_HASH_FOREACH_END(); module_names[i] = "user"; - ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) { + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), val) { if (!val->name) { /* skip special constants */ continue; @@ -1521,7 +1521,7 @@ ZEND_FUNCTION(get_defined_constants) zend_constant *constant; zval const_val; - ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) { + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) { if (!constant->name) { /* skip special constants */ continue; @@ -1606,7 +1606,7 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / zend_string *name; zval *arg; SEPARATE_ARRAY(arg_array); - ZEND_HASH_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) { ZVAL_DEREF(arg); Z_TRY_ADDREF_P(arg); zend_hash_add_new(Z_ARRVAL_P(arg_array), name, arg); @@ -1902,7 +1902,7 @@ ZEND_FUNCTION(get_extension_funcs) array = 0; } - ZEND_HASH_FOREACH_PTR(CG(function_table), zif) { + ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) { if (zif->common.type == ZEND_INTERNAL_FUNCTION && zif->internal_function.module == module) { if (!array) { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index e2ea9eacc34d2..122931ff7aebb 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -560,7 +560,7 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) array_init(&val); - ZEND_HASH_FOREACH_STR_KEY_VAL(static_variables, key, var) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(static_variables, key, var) { zval copy; if (Z_TYPE_P(var) == IS_CONSTANT_AST) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d733acdd47268..35c5f39216f08 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1728,7 +1728,7 @@ ZEND_API void zend_activate_auto_globals(void) /* {{{ */ { zend_auto_global *auto_global; - ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) { + ZEND_HASH_MAP_FOREACH_PTR(CG(auto_globals), auto_global) { if (auto_global->jit) { auto_global->armed = 1; } else if (auto_global->auto_global_callback) { @@ -5768,7 +5768,7 @@ static void zend_compile_try(zend_ast *ast) /* {{{ */ /* label: try { } must not be equal to try { label: } */ if (CG(context).labels) { zend_label *label; - ZEND_HASH_REVERSE_FOREACH_PTR(CG(context).labels, label) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(CG(context).labels, label) { if (label->opline_num == get_next_op_number()) { zend_emit_op(NULL, ZEND_NOP, NULL, NULL); } @@ -6440,7 +6440,7 @@ static void zend_compile_attributes(HashTable **attributes, zend_ast *ast, uint3 } /* Validate attributes in a secondary loop (needed to detect repeated attributes). */ - ZEND_HASH_FOREACH_PTR(*attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(*attributes, attr) { if (attr->offset != offset || NULL == (config = zend_internal_attribute_get(attr->lcname))) { continue; } @@ -6881,7 +6881,7 @@ static void compile_implicit_lexical_binds( op_array->static_variables = zend_new_array(8); } - ZEND_HASH_FOREACH_STR_KEY(&info->uses, var_name) + ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) zval *value = zend_hash_add( op_array->static_variables, var_name, &EG(uninitialized_zval)); uint32_t offset = (uint32_t)((char*)value - (char*)op_array->static_variables->arData); @@ -6930,7 +6930,7 @@ static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ static void zend_compile_implicit_closure_uses(closure_info *info) { zend_string *var_name; - ZEND_HASH_FOREACH_STR_KEY(&info->uses, var_name) + ZEND_HASH_MAP_FOREACH_STR_KEY(&info->uses, var_name) zval zv; ZVAL_NULL(&zv); zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT); diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 4494782d565c1..ab4e6e4e6f938 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -53,7 +53,7 @@ static void zend_verify_enum_properties(zend_class_entry *ce) { zend_property_info *property_info; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, property_info) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property_info) { if (zend_string_equals_literal(property_info->name, "name")) { continue; } @@ -192,7 +192,7 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func) array_init(return_value); - ZEND_HASH_FOREACH_PTR(CE_CONSTANTS_TABLE(ce), c) { + ZEND_HASH_MAP_FOREACH_PTR(CE_CONSTANTS_TABLE(ce), c) { if (!(ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE)) { continue; } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 7b9f8b849dc18..96ee0f33c3d0f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -280,7 +280,7 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) 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_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { zend_constant *c = Z_PTR_P(zv); if (_idx == EG(persistent_constants_count)) { break; @@ -291,12 +291,12 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } efree(c); zend_string_release_ex(key, 0); - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_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) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(function_table), zv) { zend_op_array *op_array = Z_PTR_P(zv); if (op_array->type == ZEND_INTERNAL_FUNCTION) { break; @@ -309,7 +309,7 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) { zend_class_entry *ce = Z_PTR_P(zv); if (ce->default_static_members_count) { @@ -323,7 +323,7 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } 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) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { if (c->ce == ce) { zval_ptr_dtor_nogc(&c->value); ZVAL_UNDEF(&c->value); @@ -333,7 +333,7 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { zend_op_array *op_array; - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->type == ZEND_USER_FUNCTION) { if (ZEND_MAP_PTR(op_array->static_variables_ptr)) { HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); @@ -412,22 +412,22 @@ void shutdown_executor(void) /* {{{ */ 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(function_table), key, zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) { zend_function *func = Z_PTR_P(zv); if (_idx == EG(persistent_functions_count)) { break; } destroy_op_array(&func->op_array); zend_string_release_ex(key, 0); - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); - ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { if (_idx == EG(persistent_classes_count)) { break; } destroy_zend_class(zv); zend_string_release_ex(key, 0); - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); } while (EG(symtable_cache_ptr) > EG(symtable_cache)) { diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 5c7a73aa2736f..a473c84d2d4e6 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -692,7 +692,6 @@ ZEND_API void ZEND_FASTCALL gc_remove_from_buffer(zend_refcounted *ref) static void gc_scan_black(zend_refcounted *ref, gc_stack *stack) { HashTable *ht = NULL; - Bucket *p, *end; zval *zv; GC_STACK_DCL(stack); @@ -765,37 +764,63 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack) handle_ht: if (!ht->nNumUsed) goto next; - p = ht->arData; - end = p + ht->nNumUsed; - while (1) { - end--; - zv = &end->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); + if (HT_IS_PACKED(ht)) { + zval *end; + + zv = ht->arPacked; + end = zv + ht->nNumUsed; + while (1) { + end--; + if (Z_REFCOUNTED_P(end)) { + break; + } + if (zv == end) goto next; + } + while (zv != end) { + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_ADDREF(ref); + if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) { + GC_REF_SET_BLACK(ref); + GC_STACK_PUSH(ref); + } + } + zv++; } - if (Z_REFCOUNTED_P(zv)) { - break; + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + while (1) { + end--; + zv = &end->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + break; + } + if (p == end) goto next; + } + while (p != end) { + zv = &p->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_ADDREF(ref); + if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) { + GC_REF_SET_BLACK(ref); + GC_STACK_PUSH(ref); + } + } + p++; } - if (p == end) goto next; - } - while (p != end) { zv = &p->val; if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - if (Z_REFCOUNTED_P(zv)) { - ref = Z_COUNTED_P(zv); - GC_ADDREF(ref); - if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) { - GC_REF_SET_BLACK(ref); - GC_STACK_PUSH(ref); - } - } - p++; - } - zv = &p->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); } ref = Z_COUNTED_P(zv); GC_ADDREF(ref); @@ -814,7 +839,6 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack) static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) { HashTable *ht = NULL; - Bucket *p, *end; zval *zv; GC_STACK_DCL(stack); @@ -889,37 +913,63 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) handle_ht: if (!ht->nNumUsed) goto next; - p = ht->arData; - end = p + ht->nNumUsed; - while (1) { - end--; - zv = &end->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); + if (HT_IS_PACKED(ht)) { + zval *end; + + zv = ht->arPacked; + end = zv + ht->nNumUsed; + while (1) { + end--; + if (Z_REFCOUNTED_P(end)) { + break; + } + if (zv == end) goto next; } - if (Z_REFCOUNTED_P(zv)) { - break; + while (zv != end) { + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_DELREF(ref); + if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) { + GC_REF_SET_COLOR(ref, GC_GREY); + GC_STACK_PUSH(ref); + } + } + zv++; + } + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + while (1) { + end--; + zv = &end->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + break; + } + if (p == end) goto next; + } + while (p != end) { + zv = &p->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_DELREF(ref); + if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) { + GC_REF_SET_COLOR(ref, GC_GREY); + GC_STACK_PUSH(ref); + } + } + p++; } - if (p == end) goto next; - } - while (p != end) { zv = &p->val; if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - if (Z_REFCOUNTED_P(zv)) { - ref = Z_COUNTED_P(zv); - GC_DELREF(ref); - if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) { - GC_REF_SET_COLOR(ref, GC_GREY); - GC_STACK_PUSH(ref); - } - } - p++; - } - zv = &p->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); } ref = Z_COUNTED_P(zv); GC_DELREF(ref); @@ -991,7 +1041,6 @@ static void gc_mark_roots(gc_stack *stack) static void gc_scan(zend_refcounted *ref, gc_stack *stack) { - Bucket *p, *end; zval *zv; GC_STACK_DCL(stack); @@ -1052,36 +1101,61 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack) HashTable *ht = (HashTable *)ref; ZEND_ASSERT(ht != &EG(symbol_table)); if (!ht->nNumUsed) goto next; - p = ht->arData; - end = p + ht->nNumUsed; - while (1) { - end--; - zv = &end->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); + if (HT_IS_PACKED(ht)) { + zval *end; + + zv = ht->arPacked; + end = zv + ht->nNumUsed; + while (1) { + end--; + if (Z_REFCOUNTED_P(end)) { + break; + } + if (zv == end) goto next; } - if (Z_REFCOUNTED_P(zv)) { - break; + while (zv != end) { + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + if (GC_REF_CHECK_COLOR(ref, GC_GREY)) { + GC_REF_SET_COLOR(ref, GC_WHITE); + GC_STACK_PUSH(ref); + } + } + zv++; + } + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + while (1) { + end--; + zv = &end->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + break; + } + if (p == end) goto next; + } + while (p != end) { + zv = &p->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + if (GC_REF_CHECK_COLOR(ref, GC_GREY)) { + GC_REF_SET_COLOR(ref, GC_WHITE); + GC_STACK_PUSH(ref); + } + } + p++; } - if (p == end) goto next; - } - while (p != end) { zv = &p->val; if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - if (Z_REFCOUNTED_P(zv)) { - ref = Z_COUNTED_P(zv); - if (GC_REF_CHECK_COLOR(ref, GC_GREY)) { - GC_REF_SET_COLOR(ref, GC_WHITE); - GC_STACK_PUSH(ref); - } - } - p++; - } - zv = &p->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); } ref = Z_COUNTED_P(zv); if (GC_REF_CHECK_COLOR(ref, GC_GREY)) { @@ -1150,7 +1224,6 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta { int count = 0; HashTable *ht = NULL; - Bucket *p, *end; zval *zv; GC_STACK_DCL(stack); @@ -1240,37 +1313,63 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta handle_ht: if (!ht->nNumUsed) goto next; - p = ht->arData; - end = p + ht->nNumUsed; - while (1) { - end--; - zv = &end->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); + if (HT_IS_PACKED(ht)) { + zval *end; + + zv = ht->arPacked; + end = zv + ht->nNumUsed; + while (1) { + end--; + if (Z_REFCOUNTED_P(end)) { + break; + } + if (zv == end) goto next; } - if (Z_REFCOUNTED_P(zv)) { - break; + while (zv != end) { + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_ADDREF(ref); + if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) { + GC_REF_SET_BLACK(ref); + GC_STACK_PUSH(ref); + } + } + zv++; + } + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + while (1) { + end--; + zv = &end->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + break; + } + if (p == end) goto next; + } + while (p != end) { + zv = &p->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_ADDREF(ref); + if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) { + GC_REF_SET_BLACK(ref); + GC_STACK_PUSH(ref); + } + } + p++; } - if (p == end) goto next; - } - while (p != end) { zv = &p->val; if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - if (Z_REFCOUNTED_P(zv)) { - ref = Z_COUNTED_P(zv); - GC_ADDREF(ref); - if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) { - GC_REF_SET_BLACK(ref); - GC_STACK_PUSH(ref); - } - } - p++; - } - zv = &p->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); } ref = Z_COUNTED_P(zv); GC_ADDREF(ref); @@ -1329,7 +1428,6 @@ static int gc_collect_roots(uint32_t *flags, gc_stack *stack) static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffer *root, gc_stack *stack) { HashTable *ht = NULL; - Bucket *p, *end; zval *zv; int count = 0; GC_STACK_DCL(stack); @@ -1397,33 +1495,55 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe } if (!ht->nNumUsed) goto next; - p = ht->arData; - end = p + ht->nNumUsed; - while (1) { - end--; - zv = &end->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); + if (HT_IS_PACKED(ht)) { + zval *end; + + zv = ht->arPacked; + end = zv + ht->nNumUsed; + while (1) { + end--; + if (Z_REFCOUNTED_P(end)) { + break; + } + if (zv == end) goto next; } - if (Z_REFCOUNTED_P(zv)) { - break; + while (zv != end) { + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_STACK_PUSH(ref); + } + zv++; + } + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + while (1) { + end--; + zv = &end->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + break; + } + if (p == end) goto next; + } + while (p != end) { + zv = &p->val; + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + if (Z_REFCOUNTED_P(zv)) { + ref = Z_COUNTED_P(zv); + GC_STACK_PUSH(ref); + } + p++; } - if (p == end) goto next; - } - while (p != end) { zv = &p->val; if (Z_TYPE_P(zv) == IS_INDIRECT) { zv = Z_INDIRECT_P(zv); } - if (Z_REFCOUNTED_P(zv)) { - ref = Z_COUNTED_P(zv); - GC_STACK_PUSH(ref); - } - p++; - } - zv = &p->val; - if (Z_TYPE_P(zv) == IS_INDIRECT) { - zv = Z_INDIRECT_P(zv); } ref = Z_COUNTED_P(zv); continue; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b7cc9aea8cdc5..965b9edb60b8f 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -608,28 +608,46 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener HashTable *ht = Z_ARR(generator->values); HashPosition pos = Z_FE_POS(generator->values); - Bucket *p; - do { - if (UNEXPECTED(pos >= ht->nNumUsed)) { - /* Reached end of array */ - goto failure; - } + if (HT_IS_PACKED(ht)) { + do { + if (UNEXPECTED(pos >= ht->nNumUsed)) { + /* Reached end of array */ + goto failure; + } - p = &ht->arData[pos]; - value = &p->val; - pos++; - } while (Z_ISUNDEF_P(value)); + value = &ht->arPacked[pos]; + pos++; + } while (Z_ISUNDEF_P(value)); - zval_ptr_dtor(&generator->value); - ZVAL_COPY(&generator->value, value); + zval_ptr_dtor(&generator->value); + ZVAL_COPY(&generator->value, value); - zval_ptr_dtor(&generator->key); - if (p->key) { - ZVAL_STR_COPY(&generator->key, p->key); + zval_ptr_dtor(&generator->key); + ZVAL_LONG(&generator->key, pos - 1); } else { - ZVAL_LONG(&generator->key, p->h); - } + Bucket *p; + do { + if (UNEXPECTED(pos >= ht->nNumUsed)) { + /* Reached end of array */ + goto failure; + } + + p = &ht->arData[pos]; + value = &p->val; + pos++; + } while (Z_ISUNDEF_P(value)); + + zval_ptr_dtor(&generator->value); + ZVAL_COPY(&generator->value, value); + + zval_ptr_dtor(&generator->key); + if (p->key) { + ZVAL_STR_COPY(&generator->key, p->key); + } else { + ZVAL_LONG(&generator->key, p->h); + } + } Z_FE_POS(generator->values) = pos; } else { zend_object_iterator *iter = (zend_object_iterator *) Z_OBJ(generator->values); diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 8ee292106a6b3..24c4ced4b434a 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -148,12 +148,12 @@ static zend_always_inline void zend_hash_real_init_packed_ex(HashTable *ht) void *data; if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) { - data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), 1); + data = pemalloc(HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK), 1); } else if (EXPECTED(ht->nTableSize == HT_MIN_SIZE)) { /* Use specialized API with constant allocation amount for a particularly common case. */ - data = emalloc(HT_SIZE_EX(HT_MIN_SIZE, HT_MIN_MASK)); + data = emalloc(HT_PACKED_SIZE_EX(HT_MIN_SIZE, HT_MIN_MASK)); } else { - data = emalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK)); + data = emalloc(HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK)); } HT_SET_DATA_ADDR(ht, data); /* Don't overwrite iterator count. */ @@ -283,21 +283,16 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize) ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2) { - Bucket *p; + zval *zv; HashTable *ht = emalloc(sizeof(HashTable)); _zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, 0); ht->nNumUsed = ht->nNumOfElements = ht->nNextFreeElement = 2; zend_hash_real_init_packed_ex(ht); - p = ht->arData; - ZVAL_COPY_VALUE(&p->val, val1); - p->h = 0; - p->key = NULL; - - p++; - ZVAL_COPY_VALUE(&p->val, val2); - p->h = 1; - p->key = NULL; + zv = ht->arPacked; + ZVAL_COPY_VALUE(zv, val1); + zv++; + ZVAL_COPY_VALUE(zv, val2); return ht; } @@ -308,7 +303,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht) zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket)); } ht->nTableSize += ht->nTableSize; - HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); + HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_PACKED_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); } ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, bool packed) @@ -338,7 +333,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_real_init_mixed(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht) { void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; + zval *src = ht->arPacked; + Bucket *dst; + uint32_t i; uint32_t nSize = ht->nTableSize; HT_ASSERT_RC1(ht); @@ -346,7 +343,14 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht) new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize); HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); + dst = ht->arData; + for (i = 0; i < ht->nNumUsed; i++) { + ZVAL_COPY_VALUE(&dst->val, src); + dst->h = i; + dst->key = NULL; + dst++; + src++; + } pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); zend_hash_rehash(ht); } @@ -354,15 +358,22 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht) { void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; + Bucket *src = ht->arData; + zval *dst; + uint32_t i; HT_ASSERT_RC1(ht); - new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); + new_data = pemalloc(HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); HT_FLAGS(ht) |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS; ht->nTableMask = HT_MIN_MASK; HT_SET_DATA_ADDR(ht, new_data); HT_HASH_RESET_PACKED(ht); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); + dst = ht->arPacked; + for (i = 0; i < ht->nNumUsed; i++) { + ZVAL_COPY_VALUE(dst, &src->val); + dst++; + src++; + } pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); } @@ -377,13 +388,13 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool zend_hash_real_init(ht, packed); } else { if (packed) { - ZEND_ASSERT(HT_FLAGS(ht) & HASH_FLAG_PACKED); + ZEND_ASSERT(HT_IS_PACKED(ht)); if (nSize > ht->nTableSize) { ht->nTableSize = zend_hash_check_size(nSize); - HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); + HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_PACKED_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); } } else { - ZEND_ASSERT(!(HT_FLAGS(ht) & HASH_FLAG_PACKED)); + ZEND_ASSERT(!HT_IS_PACKED(ht)); if (nSize > ht->nTableSize) { void *new_data, *old_data = HT_GET_DATA_ADDR(ht); Bucket *old_buckets = ht->arData; @@ -405,6 +416,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed) Bucket *p, *end, *arData; uint32_t nIndex; + ZEND_ASSERT(!HT_IS_PACKED(ht)); arData = ht->arData; p = arData + ht->nNumUsed; end = arData + nNumUsed; @@ -429,7 +441,7 @@ static uint32_t zend_array_recalc_elements(HashTable *ht) zval *val; uint32_t num = ht->nNumOfElements; - ZEND_HASH_FOREACH_VAL(ht, val) { + ZEND_HASH_MAP_FOREACH_VAL(ht, val) { if (Z_TYPE_P(val) == IS_INDIRECT) { if (UNEXPECTED(Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF)) { num--; @@ -459,8 +471,14 @@ ZEND_API uint32_t zend_array_count(HashTable *ht) static zend_always_inline HashPosition _zend_hash_get_valid_pos(const HashTable *ht, HashPosition pos) { - while (pos < ht->nNumUsed && Z_ISUNDEF(ht->arData[pos].val)) { - pos++; + if (HT_IS_PACKED(ht)) { + while (pos < ht->nNumUsed && Z_ISUNDEF(ht->arPacked[pos])) { + pos++; + } + } else { + while (pos < ht->nNumUsed && Z_ISUNDEF(ht->arData[pos].val)) { + pos++; + } } return pos; } @@ -990,6 +1008,7 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, uint32_t nIndex; uint32_t idx; Bucket *p; + zval *zv; IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); @@ -998,41 +1017,48 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, h = 0; } - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(ht)) { if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) != (HASH_ADD_NEW|HASH_ADD_NEXT) && h < ht->nNumUsed) { - p = ht->arData + h; - if (Z_TYPE(p->val) != IS_UNDEF) { + zv = ht->arPacked + h; + if (Z_TYPE_P(zv) != IS_UNDEF) { if (flag & HASH_LOOKUP) { - return &p->val; + return zv; } replace: if (flag & HASH_ADD) { return NULL; } if (ht->pDestructor) { - ht->pDestructor(&p->val); + ht->pDestructor(zv); } - ZVAL_COPY_VALUE(&p->val, pData); - return &p->val; + ZVAL_COPY_VALUE(zv, pData); + return zv; } else { /* we have to keep the order :( */ goto convert_to_hash; } } else if (EXPECTED(h < ht->nTableSize)) { add_to_packed: - p = ht->arData + h; + zv = ht->arPacked + h; /* incremental initialization of empty Buckets */ if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) != (HASH_ADD_NEW|HASH_ADD_NEXT)) { if (h > ht->nNumUsed) { - Bucket *q = ht->arData + ht->nNumUsed; - while (q != p) { - ZVAL_UNDEF(&q->val); + zval *q = ht->arPacked + ht->nNumUsed; + while (q != zv) { + ZVAL_UNDEF(q); q++; } } } ht->nNextFreeElement = ht->nNumUsed = h + 1; - goto add; + ht->nNumOfElements++; + if (flag & HASH_LOOKUP) { + ZVAL_NULL(zv); + } else { + ZVAL_COPY_VALUE(zv, pData); + } + + return zv; } else if ((h >> 1) < ht->nTableSize && (ht->nTableSize >> 1) < ht->nNumOfElements) { zend_hash_packed_grow(ht); @@ -1058,6 +1084,7 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, return &p->val; } ZEND_ASSERT((flag & HASH_ADD_NEW) == 0); + zv = &p->val; goto replace; } } @@ -1072,7 +1099,6 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, if ((zend_long)h >= ht->nNextFreeElement) { ht->nNextFreeElement = (zend_long)h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; } -add: ht->nNumOfElements++; p->h = h; p->key = NULL; @@ -1141,7 +1167,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); - ZEND_ASSERT(!(HT_FLAGS(ht) & HASH_FLAG_PACKED)); + ZEND_ASSERT(!HT_IS_PACKED(ht)); p = zend_hash_find_bucket(ht, key, 0); if (UNEXPECTED(p)) { @@ -1199,6 +1225,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); + ZEND_ASSERT(!HT_IS_PACKED(ht)); if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */ zend_hash_rehash(ht); } else if (ht->nTableSize < HT_MAX_SIZE) { /* Let's double the table size */ @@ -1310,14 +1337,49 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht) } } -static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev) +static zend_always_inline void _zend_hash_packed_del_val(HashTable *ht, uint32_t idx, zval *zv) { - if (!(HT_FLAGS(ht) & HASH_FLAG_PACKED)) { - if (prev) { - Z_NEXT(prev->val) = Z_NEXT(p->val); - } else { - HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val); + idx = HT_HASH_TO_IDX(idx); + ht->nNumOfElements--; + if (ht->nInternalPointer == idx || UNEXPECTED(HT_HAS_ITERATORS(ht))) { + uint32_t new_idx; + + new_idx = idx; + while (1) { + new_idx++; + if (new_idx >= ht->nNumUsed) { + break; + } else if (Z_TYPE(ht->arPacked[new_idx]) != IS_UNDEF) { + break; + } + } + if (ht->nInternalPointer == idx) { + ht->nInternalPointer = new_idx; } + zend_hash_iterators_update(ht, idx, new_idx); + } + if (ht->nNumUsed - 1 == idx) { + do { + ht->nNumUsed--; + } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arPacked[ht->nNumUsed-1]) == IS_UNDEF))); + ht->nInternalPointer = MIN(ht->nInternalPointer, ht->nNumUsed); + } + if (ht->pDestructor) { + zval tmp; + ZVAL_COPY_VALUE(&tmp, zv); + ZVAL_UNDEF(zv); + ht->pDestructor(&tmp); + } else { + ZVAL_UNDEF(zv); + } +} + +static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev) +{ + if (prev) { + Z_NEXT(prev->val) = Z_NEXT(p->val); + } else { + HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val); } idx = HT_HASH_TO_IDX(idx); ht->nNumOfElements--; @@ -1360,27 +1422,37 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p) { Bucket *prev = NULL; + uint32_t nIndex; + uint32_t i; - if (!(HT_FLAGS(ht) & HASH_FLAG_PACKED)) { - uint32_t nIndex = p->h | ht->nTableMask; - uint32_t i = HT_HASH(ht, nIndex); + nIndex = p->h | ht->nTableMask; + i = HT_HASH(ht, nIndex); - if (i != idx) { + if (i != idx) { + prev = HT_HASH_TO_BUCKET(ht, i); + while (Z_NEXT(prev->val) != idx) { + i = Z_NEXT(prev->val); prev = HT_HASH_TO_BUCKET(ht, i); - while (Z_NEXT(prev->val) != idx) { - i = Z_NEXT(prev->val); - prev = HT_HASH_TO_BUCKET(ht, i); - } - } + } } _zend_hash_del_el_ex(ht, idx, p, prev); } +ZEND_API void ZEND_FASTCALL zend_hash_packed_del_val(HashTable *ht, zval *zv) +{ + IS_CONSISTENT(ht); + HT_ASSERT_RC1(ht); + ZEND_ASSERT(HT_IS_PACKED(ht)); + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(zv - ht->arPacked), zv); +} + + ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p) { IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); + ZEND_ASSERT(!HT_IS_PACKED(ht)); _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p); } @@ -1546,11 +1618,11 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(ht)) { if (h < ht->nNumUsed) { - p = ht->arData + h; - if (Z_TYPE(p->val) != IS_UNDEF) { - _zend_hash_del_el_ex(ht, HT_IDX_TO_HASH(h), p, NULL); + zval *zv = ht->arPacked + h; + if (Z_TYPE_P(zv) != IS_UNDEF) { + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(h), zv); return SUCCESS; } } @@ -1573,60 +1645,81 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht) { - Bucket *p, *end; - IS_CONSISTENT(ht); HT_ASSERT(ht, GC_REFCOUNT(ht) <= 1); if (ht->nNumUsed) { - p = ht->arData; - end = p + ht->nNumUsed; - if (ht->pDestructor) { - SET_INCONSISTENT(HT_IS_DESTROYING); + if (HT_IS_PACKED(ht)) { + if (ht->pDestructor) { + zval *zv = ht->arPacked; + zval *end = zv + ht->nNumUsed; - if (HT_HAS_STATIC_KEYS_ONLY(ht)) { + SET_INCONSISTENT(HT_IS_DESTROYING); if (HT_IS_WITHOUT_HOLES(ht)) { do { - ht->pDestructor(&p->val); - } while (++p != end); + ht->pDestructor(zv); + } while (++zv != end); } else { do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { - ht->pDestructor(&p->val); + if (EXPECTED(Z_TYPE_P(zv) != IS_UNDEF)) { + ht->pDestructor(zv); } - } while (++p != end); + } while (++zv != end); } - } else if (HT_IS_WITHOUT_HOLES(ht)) { - do { - ht->pDestructor(&p->val); - if (EXPECTED(p->key)) { - zend_string_release(p->key); + SET_INCONSISTENT(HT_DESTROYED); + } + zend_hash_iterators_remove(ht); + } else { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + if (ht->pDestructor) { + SET_INCONSISTENT(HT_IS_DESTROYING); + + if (HT_HAS_STATIC_KEYS_ONLY(ht)) { + if (HT_IS_WITHOUT_HOLES(ht)) { + do { + ht->pDestructor(&p->val); + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); + } + } while (++p != end); } - } while (++p != end); - } else { - do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + } else if (HT_IS_WITHOUT_HOLES(ht)) { + do { ht->pDestructor(&p->val); if (EXPECTED(p->key)) { zend_string_release(p->key); } - } - } while (++p != end); - } - - SET_INCONSISTENT(HT_DESTROYED); - } else { - if (!HT_HAS_STATIC_KEYS_ONLY(ht)) { - do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { - if (EXPECTED(p->key)) { + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); + if (EXPECTED(p->key)) { zend_string_release(p->key); + } } - } - } while (++p != end); + } while (++p != end); + } + + SET_INCONSISTENT(HT_DESTROYED); + } else { + if (!HT_HAS_STATIC_KEYS_ONLY(ht)) { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } + } while (++p != end); + } } + zend_hash_iterators_remove(ht); } - zend_hash_iterators_remove(ht); } else if (EXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) { return; } @@ -1635,8 +1728,6 @@ ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht) { - Bucket *p, *end; - IS_CONSISTENT(ht); HT_ASSERT(ht, GC_REFCOUNT(ht) <= 1); @@ -1651,30 +1742,40 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht) goto free_ht; } - p = ht->arData; - end = p + ht->nNumUsed; SET_INCONSISTENT(HT_IS_DESTROYING); - if (HT_HAS_STATIC_KEYS_ONLY(ht)) { - do { - i_zval_ptr_dtor(&p->val); - } while (++p != end); - } else if (HT_IS_WITHOUT_HOLES(ht)) { + if (HT_IS_PACKED(ht)) { + zval *zv = ht->arPacked; + zval *end = zv + ht->nNumUsed; + do { - i_zval_ptr_dtor(&p->val); - if (EXPECTED(p->key)) { - zend_string_release_ex(p->key, 0); - } - } while (++p != end); + i_zval_ptr_dtor(zv); + } while (++zv != end); } else { - do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + if (HT_HAS_STATIC_KEYS_ONLY(ht)) { + do { + i_zval_ptr_dtor(&p->val); + } while (++p != end); + } else if (HT_IS_WITHOUT_HOLES(ht)) { + do { i_zval_ptr_dtor(&p->val); if (EXPECTED(p->key)) { zend_string_release_ex(p->key, 0); } - } - } while (++p != end); + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + i_zval_ptr_dtor(&p->val); + if (EXPECTED(p->key)) { + zend_string_release_ex(p->key, 0); + } + } + } while (++p != end); + } } } else if (EXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) { goto free_ht; @@ -1688,48 +1789,49 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht) { - Bucket *p, *end; - IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); if (ht->nNumUsed) { - p = ht->arData; - end = p + ht->nNumUsed; - if (ht->pDestructor) { - if (HT_HAS_STATIC_KEYS_ONLY(ht)) { - if (HT_IS_WITHOUT_HOLES(ht)) { - do { - ht->pDestructor(&p->val); - } while (++p != end); - } else { - do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { - ht->pDestructor(&p->val); - } - } while (++p != end); - } - } else if (HT_IS_WITHOUT_HOLES(ht)) { - do { - ht->pDestructor(&p->val); - if (EXPECTED(p->key)) { - zend_string_release(p->key); - } - } while (++p != end); - } else { - do { - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { - ht->pDestructor(&p->val); - if (EXPECTED(p->key)) { - zend_string_release(p->key); - } + if (HT_IS_PACKED(ht)) { + zval *zv = ht->arPacked; + zval *end = zv + ht->nNumUsed; + + if (ht->pDestructor) { + if (HT_HAS_STATIC_KEYS_ONLY(ht)) { + if (HT_IS_WITHOUT_HOLES(ht)) { + do { + ht->pDestructor(zv); + } while (++zv != end); + } else { + do { + if (EXPECTED(Z_TYPE_P(zv) != IS_UNDEF)) { + ht->pDestructor(zv); + } + } while (++zv != end); } - } while (++p != end); + } } } else { - if (!HT_HAS_STATIC_KEYS_ONLY(ht)) { - if (HT_IS_WITHOUT_HOLES(ht)) { + Bucket *p = ht->arData; + Bucket *end = p + ht->nNumUsed; + + if (ht->pDestructor) { + if (HT_HAS_STATIC_KEYS_ONLY(ht)) { + if (HT_IS_WITHOUT_HOLES(ht)) { + do { + ht->pDestructor(&p->val); + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); + } + } while (++p != end); + } + } else if (HT_IS_WITHOUT_HOLES(ht)) { do { + ht->pDestructor(&p->val); if (EXPECTED(p->key)) { zend_string_release(p->key); } @@ -1737,15 +1839,32 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht) } else { do { if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); if (EXPECTED(p->key)) { zend_string_release(p->key); } } } while (++p != end); } + } else { + if (!HT_HAS_STATIC_KEYS_ONLY(ht)) { + if (HT_IS_WITHOUT_HOLES(ht)) { + do { + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } + } while (++p != end); + } + } } - } - if (!(HT_FLAGS(ht) & HASH_FLAG_PACKED)) { HT_HASH_RESET(ht); } } @@ -1763,6 +1882,7 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht) HT_ASSERT_RC1(ht); if (ht->nNumUsed) { + ZEND_ASSERT(!HT_IS_PACKED(ht)); p = ht->arData; end = p + ht->nNumUsed; if (HT_HAS_STATIC_KEYS_ONLY(ht)) { @@ -1797,15 +1917,24 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht) { uint32_t idx; - Bucket *p; IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); - p = ht->arData; - for (idx = 0; idx < ht->nNumUsed; idx++, p++) { - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + if (HT_IS_PACKED(ht)) { + zval *zv = ht->arPacked; + + for (idx = 0; idx < ht->nNumUsed; idx++, zv++) { + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + } else { + Bucket *p = ht->arData; + + for (idx = 0; idx < ht->nNumUsed; idx++, p++) { + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } } if (!(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) { pefree(HT_GET_DATA_ADDR(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); @@ -1817,18 +1946,29 @@ ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht) { uint32_t idx; - Bucket *p; IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); idx = ht->nNumUsed; - p = ht->arData + ht->nNumUsed; - while (idx > 0) { - idx--; - p--; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + if (HT_IS_PACKED(ht)) { + zval *zv = ht->arPacked + ht->nNumUsed; + + while (idx > 0) { + idx--; + zv--; + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + } else { + Bucket *p = ht->arData + ht->nNumUsed; + + while (idx > 0) { + idx--; + p--; + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } } if (!(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) { @@ -1850,22 +1990,38 @@ ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht) ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func) { uint32_t idx; - Bucket *p; int result; IS_CONSISTENT(ht); + if (HT_IS_PACKED(ht)) { + for (idx = 0; idx < ht->nNumUsed; idx++) { + zval *zv = ht->arPacked + idx; - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - result = apply_func(&p->val); + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + result = apply_func(zv); - if (result & ZEND_HASH_APPLY_REMOVE) { - HT_ASSERT_RC1(ht); - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } - if (result & ZEND_HASH_APPLY_STOP) { - break; + } else { + for (idx = 0; idx < ht->nNumUsed; idx++) { + Bucket *p = ht->arData + idx; + + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + result = apply_func(&p->val); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } } } @@ -1874,22 +2030,36 @@ ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_fu ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument) { uint32_t idx; - Bucket *p; int result; IS_CONSISTENT(ht); - - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - result = apply_func(&p->val, argument); - - if (result & ZEND_HASH_APPLY_REMOVE) { - HT_ASSERT_RC1(ht); - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + if (HT_IS_PACKED(ht)) { + for (idx = 0; idx < ht->nNumUsed; idx++) { + zval *zv = ht->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + result = apply_func(zv, argument); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } - if (result & ZEND_HASH_APPLY_STOP) { - break; + } else { + for (idx = 0; idx < ht->nNumUsed; idx++) { + Bucket *p = ht->arData + idx; + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + result = apply_func(&p->val, argument); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } } } @@ -1898,31 +2068,54 @@ ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_f ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...) { uint32_t idx; - Bucket *p; va_list args; zend_hash_key hash_key; int result; IS_CONSISTENT(ht); - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - va_start(args, num_args); - hash_key.h = p->h; - hash_key.key = p->key; + if (HT_IS_PACKED(ht)) { + for (idx = 0; idx < ht->nNumUsed; idx++) { + zval *zv = ht->arPacked + idx; - result = apply_func(&p->val, num_args, args, &hash_key); + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + va_start(args, num_args); + hash_key.h = idx; + hash_key.key = NULL; - if (result & ZEND_HASH_APPLY_REMOVE) { - HT_ASSERT_RC1(ht); - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + result = apply_func(zv, num_args, args, &hash_key); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + if (result & ZEND_HASH_APPLY_STOP) { + va_end(args); + break; + } + va_end(args); } - if (result & ZEND_HASH_APPLY_STOP) { + } else { + for (idx = 0; idx < ht->nNumUsed; idx++) { + Bucket *p = ht->arData + idx; + + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + va_start(args, num_args); + hash_key.h = p->h; + hash_key.key = p->key; + + result = apply_func(&p->val, num_args, args, &hash_key); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } + if (result & ZEND_HASH_APPLY_STOP) { + va_end(args); + break; + } va_end(args); - break; } - va_end(args); } } @@ -1930,25 +2123,46 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t ap ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func) { uint32_t idx; - Bucket *p; int result; IS_CONSISTENT(ht); idx = ht->nNumUsed; - while (idx > 0) { - idx--; - p = ht->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + if (HT_IS_PACKED(ht)) { + zval *zv; - result = apply_func(&p->val); + while (idx > 0) { + idx--; + zv = ht->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; - if (result & ZEND_HASH_APPLY_REMOVE) { - HT_ASSERT_RC1(ht); - _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + result = apply_func(zv); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_packed_del_val(ht, HT_IDX_TO_HASH(idx), zv); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } - if (result & ZEND_HASH_APPLY_STOP) { - break; + } else { + Bucket *p; + + while (idx > 0) { + idx--; + p = ht->arData + idx; + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + + result = apply_func(&p->val); + + if (result & ZEND_HASH_APPLY_REMOVE) { + HT_ASSERT_RC1(ht); + _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } } } } @@ -1957,15 +2171,28 @@ ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor) { uint32_t idx; - Bucket *p; zval *new_entry, *data; IS_CONSISTENT(source); IS_CONSISTENT(target); HT_ASSERT_RC1(target); + if (HT_IS_PACKED(source)) { + for (idx = 0; idx < source->nNumUsed; idx++) { + zval *zv = source->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; + + new_entry = zend_hash_index_update(target, idx, zv); + if (pCopyConstructor) { + pCopyConstructor(new_entry); + } + } + return; + } + for (idx = 0; idx < source->nNumUsed; idx++) { - p = source->arData + idx; + Bucket *p = source->arData + idx; + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; /* INDIRECT element may point to UNDEF-ined slots */ @@ -1988,10 +2215,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, } -static zend_always_inline bool zend_array_dup_element(HashTable *source, HashTable *target, uint32_t idx, Bucket *p, Bucket *q, bool packed, bool static_keys, bool with_holes) +static zend_always_inline bool zend_array_dup_value(HashTable *source, HashTable *target, zval *data, zval *dest, bool packed, bool with_holes) { - zval *data = &p->val; - if (with_holes) { if (!packed && Z_TYPE_INFO_P(data) == IS_INDIRECT) { data = Z_INDIRECT_P(data); @@ -2022,14 +2247,21 @@ static zend_always_inline bool zend_array_dup_element(HashTable *source, HashTab Z_ADDREF_P(data); } } while (0); - ZVAL_COPY_VALUE(&q->val, data); + ZVAL_COPY_VALUE(dest, data); - q->h = p->h; - if (packed) { - q->key = NULL; - } else { + return 1; +} + +static zend_always_inline bool zend_array_dup_element(HashTable *source, HashTable *target, uint32_t idx, Bucket *p, Bucket *q, bool packed, bool static_keys, bool with_holes) +{ + if (!zend_array_dup_value(source, target, &p->val, &q->val, packed, with_holes)) { + return 0; + } + + if (!packed) { uint32_t nIndex; + q->h = p->h; q->key = p->key; if (!static_keys && q->key) { zend_string_addref(q->key); @@ -2044,14 +2276,14 @@ static zend_always_inline bool zend_array_dup_element(HashTable *source, HashTab static zend_always_inline void zend_array_dup_packed_elements(HashTable *source, HashTable *target, bool with_holes) { - Bucket *p = source->arData; - Bucket *q = target->arData; - Bucket *end = p + source->nNumUsed; + zval *p = source->arPacked; + zval *q = target->arPacked; + zval *end = p + source->nNumUsed; do { - if (!zend_array_dup_element(source, target, 0, p, q, 1, 1, with_holes)) { + if (!zend_array_dup_value(source, target, p, q, 1, with_holes)) { if (with_holes) { - ZVAL_UNDEF(&q->val); + ZVAL_UNDEF(q); } } p++; q++; @@ -2115,17 +2347,23 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; target->nTableSize = source->nTableSize; - HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); - target->nInternalPointer = source->nInternalPointer; - memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); - } else if (HT_FLAGS(source) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(source)) { + HT_SET_DATA_ADDR(target, emalloc(HT_PACKED_SIZE(target))); + target->nInternalPointer = source->nInternalPointer; + memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_PACKED_USED_SIZE(source)); + } else { + HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); + target->nInternalPointer = source->nInternalPointer; + memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); + } + } else if (HT_IS_PACKED(source)) { HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = HT_MIN_MASK; target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; target->nTableSize = source->nTableSize; - HT_SET_DATA_ADDR(target, emalloc(HT_SIZE_EX(target->nTableSize, HT_MIN_MASK))); + HT_SET_DATA_ADDR(target, emalloc(HT_PACKED_SIZE_EX(target->nTableSize, HT_MIN_MASK))); target->nInternalPointer = (source->nInternalPointer < source->nNumUsed) ? source->nInternalPointer : 0; @@ -2180,6 +2418,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source HT_ASSERT_RC1(target); if (overwrite) { + if (HT_IS_PACKED(source)) { + for (idx = 0; idx < source->nNumUsed; idx++) { + s = source->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) { + continue; + } + t = zend_hash_index_update(target, idx, s); + if (pCopyConstructor) { + pCopyConstructor(t); + } + } + return; + } + for (idx = 0; idx < source->nNumUsed; idx++) { p = source->arData + idx; s = &p->val; @@ -2202,6 +2454,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source } } } else { + if (HT_IS_PACKED(source)) { + for (idx = 0; idx < source->nNumUsed; idx++) { + s = source->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) { + continue; + } + t = zend_hash_index_add(target, idx, s); + if (t && pCopyConstructor) { + pCopyConstructor(t); + } + } + return; + } + for (idx = 0; idx < source->nNumUsed; idx++) { p = source->arData + idx; s = &p->val; @@ -2227,12 +2493,12 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source } -static bool ZEND_FASTCALL zend_hash_replace_checker_wrapper(HashTable *target, zval *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func) +static bool ZEND_FASTCALL zend_hash_replace_checker_wrapper(HashTable *target, zval *source_data, zend_ulong h, zend_string *key, void *pParam, merge_checker_func_t merge_checker_func) { zend_hash_key hash_key; - hash_key.h = p->h; - hash_key.key = p->key; + hash_key.h = h; + hash_key.key = key; return merge_checker_func(target, source_data, &hash_key, pParam); } @@ -2247,10 +2513,11 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge_ex(HashTable *target, HashTable *sou IS_CONSISTENT(target); HT_ASSERT_RC1(target); + ZEND_ASSERT(!HT_IS_PACKED(source)); for (idx = 0; idx < source->nNumUsed; idx++) { p = source->arData + idx; if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) { + if (zend_hash_replace_checker_wrapper(target, &p->val, p->h, p->key, pParam, pMergeSource)) { t = zend_hash_update(target, p->key, &p->val); if (pCopyConstructor) { pCopyConstructor(t); @@ -2299,11 +2566,12 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulon IS_CONSISTENT(ht); - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(ht)) { if (h < ht->nNumUsed) { - p = ht->arData + h; - if (Z_TYPE(p->val) != IS_UNDEF) { - return &p->val; + zval *zv = ht->arPacked + h; + + if (Z_TYPE_P(zv) != IS_UNDEF) { + return zv; } } return NULL; @@ -2318,6 +2586,7 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulo Bucket *p; IS_CONSISTENT(ht); + ZEND_ASSERT(!HT_IS_PACKED(ht)); p = zend_hash_index_find_bucket(ht, h); return p ? &p->val : NULL; @@ -2342,11 +2611,21 @@ ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, Has HT_ASSERT(ht, &ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1); idx = ht->nNumUsed; - while (idx > 0) { - idx--; - if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { - *pos = idx; - return; + if (HT_IS_PACKED(ht)) { + while (idx > 0) { + idx--; + if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) { + *pos = idx; + return; + } + } + } else { + while (idx > 0) { + idx--; + if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { + *pos = idx; + return; + } } } *pos = ht->nNumUsed; @@ -2362,15 +2641,29 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, Hash idx = _zend_hash_get_valid_pos(ht, *pos); if (idx < ht->nNumUsed) { - while (1) { - idx++; - if (idx >= ht->nNumUsed) { - *pos = ht->nNumUsed; - return SUCCESS; + if (HT_IS_PACKED(ht)) { + while (1) { + idx++; + if (idx >= ht->nNumUsed) { + *pos = ht->nNumUsed; + return SUCCESS; + } + if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) { + *pos = idx; + return SUCCESS; + } } - if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { - *pos = idx; - return SUCCESS; + } else { + while (1) { + idx++; + if (idx >= ht->nNumUsed) { + *pos = ht->nNumUsed; + return SUCCESS; + } + if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { + *pos = idx; + return SUCCESS; + } } } } else { @@ -2386,11 +2679,21 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, Ha HT_ASSERT(ht, &ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1); if (idx < ht->nNumUsed) { - while (idx > 0) { - idx--; - if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { - *pos = idx; - return SUCCESS; + if (HT_IS_PACKED(ht)) { + while (idx > 0) { + idx--; + if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) { + *pos = idx; + return SUCCESS; + } + } + } else { + while (idx > 0) { + idx--; + if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { + *pos = idx; + return SUCCESS; + } } } *pos = ht->nNumUsed; @@ -2410,6 +2713,10 @@ ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zen IS_CONSISTENT(ht); idx = _zend_hash_get_valid_pos(ht, *pos); if (idx < ht->nNumUsed) { + if (HT_IS_PACKED(ht)) { + *num_index = idx; + return HASH_KEY_IS_LONG; + } p = ht->arData + idx; if (p->key) { *str_index = p->key; @@ -2432,6 +2739,10 @@ ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *h if (idx >= ht->nNumUsed) { ZVAL_NULL(key); } else { + if (HT_IS_PACKED(ht)) { + ZVAL_LONG(key, idx); + return; + } p = ht->arData + idx; if (p->key) { ZVAL_STR_COPY(key, p->key); @@ -2449,6 +2760,9 @@ ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, Hash IS_CONSISTENT(ht); idx = _zend_hash_get_valid_pos(ht, *pos); if (idx < ht->nNumUsed) { + if (HT_IS_PACKED(ht)) { + return HASH_KEY_IS_LONG; + } p = ht->arData + idx; if (p->key) { return HASH_KEY_IS_STRING; @@ -2468,6 +2782,9 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPo IS_CONSISTENT(ht); idx = _zend_hash_get_valid_pos(ht, *pos); if (idx < ht->nNumUsed) { + if (HT_IS_PACKED(ht)) { + return &ht->arPacked[idx]; + } p = ht->arData + idx; return &p->val; } else { @@ -2531,6 +2848,10 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b return; } + if (HT_IS_PACKED(ht)) { + zend_hash_packed_to_hash(ht); // TODO: ??? + } + if (HT_IS_WITHOUT_HOLES(ht)) { /* Store original order of elements in extra space to allow stable sorting. */ for (i = 0; i < ht->nNumUsed; i++) { @@ -2552,7 +2873,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b sort((void *)ht->arData, ht->nNumUsed, sizeof(Bucket), (compare_func_t) compar, (swap_func_t)(renumber? zend_hash_bucket_renum_swap : - ((HT_FLAGS(ht) & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap))); + (HT_IS_PACKED(ht) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap))); ht->nInternalPointer = 0; @@ -2568,7 +2889,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b ht->nNextFreeElement = i; } - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(ht)) { if (!renumber) { zend_hash_packed_to_hash(ht); } @@ -2576,12 +2897,19 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b if (renumber) { void *new_data, *old_data = HT_GET_DATA_ADDR(ht); Bucket *old_buckets = ht->arData; + zval *zv; - new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); + new_data = pemalloc(HT_PACKED_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); HT_FLAGS(ht) |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS; ht->nTableMask = HT_MIN_MASK; HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); + p = old_buckets; + zv = ht->arPacked; + for (i = 0; i < ht->nTableSize; i++) { + ZVAL_COPY_VALUE(zv, &p->val); + zv++; + p++; + } pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); HT_HASH_RESET_PACKED(ht); } else { @@ -2592,58 +2920,82 @@ ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, b static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered) { uint32_t idx1, idx2; + zend_string *key1, *key2; + zend_ulong h1, h2; + zval *pData1, *pData2;; + int result; if (ht1->nNumOfElements != ht2->nNumOfElements) { return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1; } for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) { - Bucket *p1 = ht1->arData + idx1, *p2; - zval *pData1, *pData2; - int result; + if (HT_IS_PACKED(ht1)) { + pData1 = ht1->arPacked + idx1; + h1 = idx1; + key1 = NULL; + } else { + Bucket *p = ht1->arData + idx1; + pData1 = &p->val; + h1 = p->h; + key1 = p->key; + } - if (Z_TYPE(p1->val) == IS_UNDEF) continue; + if (Z_TYPE_P(pData1) == IS_UNDEF) continue; if (ordered) { - while (1) { - ZEND_ASSERT(idx2 != ht2->nNumUsed); - p2 = ht2->arData + idx2; - if (Z_TYPE(p2->val) != IS_UNDEF) break; - idx2++; - } - if (p1->key == NULL && p2->key == NULL) { /* numeric indices */ - if (p1->h != p2->h) { - return p1->h > p2->h ? 1 : -1; + if (HT_IS_PACKED(ht2)) { + while (1) { + ZEND_ASSERT(idx2 != ht2->nNumUsed); + pData2 = ht2->arPacked + idx2; + h2 = idx2; + key2 = NULL; + if (Z_TYPE_P(pData2) != IS_UNDEF) break; + idx2++; + } + } else { + while (1) { + Bucket *p; + ZEND_ASSERT(idx2 != ht2->nNumUsed); + p = ht2->arData + idx2; + pData2 = &p->val; + h2 = p->h; + key2 = p->key; + if (Z_TYPE_P(pData2) != IS_UNDEF) break; + idx2++; + } + } + if (key1 == NULL && key2 == NULL) { /* numeric indices */ + if (h1 != h2) { + return h1 > h2 ? 1 : -1; } - } else if (p1->key != NULL && p2->key != NULL) { /* string indices */ - if (ZSTR_LEN(p1->key) != ZSTR_LEN(p2->key)) { - return ZSTR_LEN(p1->key) > ZSTR_LEN(p2->key) ? 1 : -1; + } else if (key1 != NULL && key2 != NULL) { /* string indices */ + if (ZSTR_LEN(key1) != ZSTR_LEN(key2)) { + return ZSTR_LEN(key1) > ZSTR_LEN(key2) ? 1 : -1; } - result = memcmp(ZSTR_VAL(p1->key), ZSTR_VAL(p2->key), ZSTR_LEN(p1->key)); + result = memcmp(ZSTR_VAL(key1), ZSTR_VAL(key2), ZSTR_LEN(key1)); if (result != 0) { return result; } } else { /* Mixed key types: A string key is considered as larger */ - return p1->key != NULL ? 1 : -1; + return key1 != NULL ? 1 : -1; } - pData2 = &p2->val; idx2++; } else { - if (p1->key == NULL) { /* numeric index */ - pData2 = zend_hash_index_find(ht2, p1->h); + if (key1 == NULL) { /* numeric index */ + pData2 = zend_hash_index_find(ht2, h1); if (pData2 == NULL) { return 1; } } else { /* string index */ - pData2 = zend_hash_find(ht2, p1->key); + pData2 = zend_hash_find(ht2, key1); if (pData2 == NULL) { return 1; } } } - pData1 = &p1->val; if (Z_TYPE_P(pData1) == IS_INDIRECT) { pData1 = Z_INDIRECT_P(pData1); } @@ -2694,10 +3046,10 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co } -ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, bucket_compare_func_t compar, uint32_t flag) +ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag) { uint32_t idx; - Bucket *p, *res; + zval *res; IS_CONSISTENT(ht); @@ -2705,30 +3057,60 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, bucket_compar return NULL; } - idx = 0; - while (1) { - if (idx == ht->nNumUsed) { - return NULL; + if (HT_IS_PACKED(ht)) { + zval *zv; + + idx = 0; + while (1) { + if (idx == ht->nNumUsed) { + return NULL; + } + if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) break; + idx++; } - if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break; - idx++; - } - res = ht->arData + idx; - for (; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + res = ht->arPacked + idx; + for (; idx < ht->nNumUsed; idx++) { + zv = ht->arPacked + idx; + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue; - if (flag) { - if (compar(res, p) < 0) { /* max */ - res = p; + if (flag) { + if (compar(res, zv) < 0) { /* max */ + res = zv; + } + } else { + if (compar(res, zv) > 0) { /* min */ + res = zv; + } } - } else { - if (compar(res, p) > 0) { /* min */ - res = p; + } + } else { + Bucket *p; + + idx = 0; + while (1) { + if (idx == ht->nNumUsed) { + return NULL; + } + if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break; + idx++; + } + res = &ht->arData[idx].val; + for (; idx < ht->nNumUsed; idx++) { + p = ht->arData + idx; + if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; + + if (flag) { + if (compar(res, &p->val) < 0) { /* max */ + res = &p->val; + } + } else { + if (compar(res, &p->val) > 0) { /* min */ + res = &p->val; + } } } } - return &res->val; + return res; } ZEND_API bool ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx) @@ -2784,7 +3166,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht) goto convert; } - ZEND_HASH_FOREACH_STR_KEY(ht, str_key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, str_key) { if (!str_key) { goto convert; } @@ -2833,16 +3215,18 @@ ZEND_API HashTable* ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, bool zend_string *str_key; zval *zv; - ZEND_HASH_FOREACH_STR_KEY(ht, str_key) { - /* The `str_key &&` here might seem redundant: property tables should - * only have string keys. Unfortunately, this isn't true, at the very - * least because of ArrayObject, which stores a symtable where the - * property table should be. - */ - if (str_key && ZEND_HANDLE_NUMERIC(str_key, num_key)) { - goto convert; - } - } ZEND_HASH_FOREACH_END(); + if (!HT_IS_PACKED(ht)) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, str_key) { + /* The `str_key &&` here might seem redundant: property tables should + * only have string keys. Unfortunately, this isn't true, at the very + * least because of ArrayObject, which stores a symtable where the + * property table should be. + */ + if (str_key && ZEND_HANDLE_NUMERIC(str_key, num_key)) { + goto convert; + } + } ZEND_HASH_FOREACH_END(); + } if (always_duplicate) { return zend_array_dup(ht); @@ -2858,7 +3242,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, bool { HashTable *new_ht = zend_new_array(zend_hash_num_elements(ht)); - ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, str_key, zv) { + ZEND_HASH_MAP_FOREACH_KEY_VAL_IND(ht, num_key, str_key, zv) { do { if (Z_OPT_REFCOUNTED_P(zv)) { if (Z_ISREF_P(zv) && Z_REFCOUNT_P(zv) == 1) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 092682d67713a..b7559257d27e5 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -170,6 +170,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char * ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len); ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h); ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p); +ZEND_API void ZEND_FASTCALL zend_hash_packed_del_val(HashTable *ht, zval *zv); /* Data retrieval */ ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key); @@ -192,7 +193,7 @@ static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_stri #define ZEND_HASH_INDEX_FIND(_ht, _h, _ret, _not_found) do { \ if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \ if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \ - _ret = &_ht->arData[_h].val; \ + _ret = &_ht->arPacked[_h]; \ if (UNEXPECTED(Z_TYPE_P(_ret) == IS_UNDEF)) { \ goto _not_found; \ } \ @@ -215,7 +216,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h) #define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret) do { \ if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \ if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \ - _ret = &_ht->arData[_h].val; \ + _ret = &_ht->arPacked[_h]; \ if (EXPECTED(Z_TYPE_P(_ret) != IS_UNDEF)) { \ break; \ } \ @@ -284,7 +285,7 @@ ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q); typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b); ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered); ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber); -ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, bucket_compare_func_t compar, uint32_t flag); +ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag); #define zend_hash_sort(ht, compare_func, renumber) \ zend_hash_sort_ex(ht, zend_sort, compare_func, renumber) @@ -958,15 +959,68 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, #define zend_hash_get_current_data_ptr(ht) \ zend_hash_get_current_data_ptr_ex(ht, &(ht)->nInternalPointer) +/* Common hash/packed array iterators */ +#if 0 +# define ZEND_HASH_ELEMENT_SIZE(__ht) \ + (HT_IS_PACKED(__ht) ? sizeof(zval) : sizeof(Bucket)) +#else /* optimized version */ +# define ZEND_HASH_ELEMENT_SIZE(__ht) \ + (sizeof(zval) + (~HT_FLAGS(__ht) & HASH_FLAG_PACKED) * ((sizeof(Bucket)-sizeof(zval))/HASH_FLAG_PACKED)) +#endif + +#define ZEND_HASH_ELEMENT_EX(__ht, _idx, _size) \ + ((zval*)(((char*)(__ht)->arPacked) + ((_idx) * (_size)))) + +#define ZEND_HASH_ELEMENT(__ht, _idx) \ + ZEND_HASH_ELEMENT_EX(__ht, _idx, ZEND_HASH_ELEMENT_SIZE(__ht)) + +#define ZEND_HASH_NEXT_ELEMENT(_el, _size) \ + ((zval*)(((char*)(_el)) + (_size))) + +#define ZEND_HASH_PREV_ELEMENT(_el, _size) \ + ((zval*)(((char*)(_el)) - (_size))) + +#define _ZEND_HASH_FOREACH_VAL(_ht) do { \ + HashTable *__ht = (_ht); \ + uint32_t _count = __ht->nNumUsed; \ + size_t _size = ZEND_HASH_ELEMENT_SIZE(__ht); \ + zval *_z = __ht->arPacked; \ + for (; _count > 0; _z = ZEND_HASH_NEXT_ELEMENT(_z, _size), _count--) { \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + +#define _ZEND_HASH_REVERSE_FOREACH_VAL(_ht) do { \ + HashTable *__ht = (_ht); \ + uint32_t _idx = __ht->nNumUsed; \ + size_t _size = ZEND_HASH_ELEMENT_SIZE(__ht); \ + zval *_z = ZEND_HASH_ELEMENT_EX(__ht, _idx, _size); \ + for (;_idx > 0; _idx--) { \ + _z = ZEND_HASH_PREV_ELEMENT(_z, _size); \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + #define ZEND_HASH_FOREACH_FROM(_ht, indirect, _from) do { \ HashTable *__ht = (_ht); \ - Bucket *_p = __ht->arData + (_from); \ - Bucket *_end = __ht->arData + __ht->nNumUsed; \ - for (; _p != _end; _p++) { \ - zval *_z = &_p->val; \ - if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ - _z = Z_INDIRECT_P(_z); \ + zend_ulong __h; \ + zend_string *__key = NULL; \ + uint32_t _idx = (_from); \ + size_t _size = ZEND_HASH_ELEMENT_SIZE(__ht); \ + zval *__z = ZEND_HASH_ELEMENT_EX(__ht, _idx, _size); \ + uint32_t _count = __ht->nNumUsed - _idx; \ + for (;_count > 0; _count--) { \ + zval *_z = __z; \ + if (HT_IS_PACKED(__ht)) { \ + __z++; \ + __h = _idx; \ + _idx++; \ + } else { \ + Bucket *_p = (Bucket*)__z; \ + __z = &(_p + 1)->val; \ + __h = _p->h; \ + __key = _p->key; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ + _z = Z_INDIRECT_P(_z); \ + } \ } \ + (void) __h; (void) __key; (void) _idx; \ if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; #define ZEND_HASH_FOREACH(_ht, indirect) ZEND_HASH_FOREACH_FROM(_ht, indirect, 0) @@ -974,14 +1028,28 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, #define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \ HashTable *__ht = (_ht); \ uint32_t _idx = __ht->nNumUsed; \ - Bucket *_p = __ht->arData + _idx; \ zval *_z; \ - for (_idx = __ht->nNumUsed; _idx > 0; _idx--) { \ - _p--; \ - _z = &_p->val; \ - if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ - _z = Z_INDIRECT_P(_z); \ + zend_ulong __h; \ + zend_string *__key = NULL; \ + size_t _size = ZEND_HASH_ELEMENT_SIZE(__ht); \ + zval *__z = ZEND_HASH_ELEMENT_EX(__ht, _idx, _size); \ + for (;_idx > 0; _idx--) { \ + if (HT_IS_PACKED(__ht)) { \ + __z--; \ + _z = __z; \ + __h = _idx - 1; \ + } else { \ + Bucket *_p = (Bucket*)__z; \ + _p--; \ + __z = &_p->val; \ + _z = __z; \ + __h = _p->h; \ + __key = _p->key; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ + _z = Z_INDIRECT_P(_z); \ + } \ } \ + (void) __h; (void) __key; (void) __z; \ if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; #define ZEND_HASH_FOREACH_END() \ @@ -989,44 +1057,23 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, } while (0) #define ZEND_HASH_FOREACH_END_DEL() \ - __ht->nNumOfElements--; \ - do { \ - uint32_t j = HT_IDX_TO_HASH(_idx - 1); \ - uint32_t nIndex = _p->h | __ht->nTableMask; \ - uint32_t i = HT_HASH(__ht, nIndex); \ - if (UNEXPECTED(j != i)) { \ - Bucket *prev = HT_HASH_TO_BUCKET(__ht, i); \ - while (Z_NEXT(prev->val) != j) { \ - i = Z_NEXT(prev->val); \ - prev = HT_HASH_TO_BUCKET(__ht, i); \ - } \ - Z_NEXT(prev->val) = Z_NEXT(_p->val); \ - } else { \ - HT_HASH(__ht, nIndex) = Z_NEXT(_p->val); \ - } \ - } while (0); \ - } \ - __ht->nNumUsed = _idx; \ - } while (0) + ZEND_HASH_MAP_FOREACH_END_DEL() #define ZEND_HASH_FOREACH_BUCKET(ht, _bucket) \ - ZEND_HASH_FOREACH(ht, 0); \ - _bucket = _p; + ZEND_HASH_MAP_FOREACH_BUCKET(ht, _bucket) #define ZEND_HASH_FOREACH_BUCKET_FROM(ht, _bucket, _from) \ - ZEND_HASH_FOREACH_FROM(ht, 0, _from); \ - _bucket = _p; + ZEND_HASH_MAP_FOREACH_BUCKET_FROM(ht, _bucket, _from) #define ZEND_HASH_REVERSE_FOREACH_BUCKET(ht, _bucket) \ - ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _bucket = _p; + ZEND_HASH_MAP_REVERSE_FOREACH_BUCKET(ht, _bucket) #define ZEND_HASH_FOREACH_VAL(ht, _val) \ - ZEND_HASH_FOREACH(ht, 0); \ + _ZEND_HASH_FOREACH_VAL(ht); \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_VAL(ht, _val) \ - ZEND_HASH_REVERSE_FOREACH(ht, 0); \ + _ZEND_HASH_REVERSE_FOREACH_VAL(ht); \ _val = _z; #define ZEND_HASH_FOREACH_VAL_IND(ht, _val) \ @@ -1038,7 +1085,7 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, _val = _z; #define ZEND_HASH_FOREACH_PTR(ht, _ptr) \ - ZEND_HASH_FOREACH(ht, 0); \ + _ZEND_HASH_FOREACH_VAL(ht); \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_FOREACH_PTR_FROM(ht, _ptr, _from) \ @@ -1046,126 +1093,402 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, _ptr = Z_PTR_P(_z); #define ZEND_HASH_REVERSE_FOREACH_PTR(ht, _ptr) \ - ZEND_HASH_REVERSE_FOREACH(ht, 0); \ + _ZEND_HASH_REVERSE_FOREACH_VAL(ht, 0); \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_FOREACH_NUM_KEY(ht, _h) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; + _h = __h; #define ZEND_HASH_REVERSE_FOREACH_NUM_KEY(ht, _h) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _h = _p->h; + _h = __h; #define ZEND_HASH_FOREACH_STR_KEY(ht, _key) \ ZEND_HASH_FOREACH(ht, 0); \ - _key = _p->key; + _key = __key; #define ZEND_HASH_REVERSE_FOREACH_STR_KEY(ht, _key) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _key = _p->key; + _key = __key; #define ZEND_HASH_FOREACH_KEY(ht, _h, _key) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; \ - _key = _p->key; + _h = __h; \ + _key = __key; #define ZEND_HASH_REVERSE_FOREACH_KEY(ht, _h, _key) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _h = _p->h; \ - _key = _p->key; + _h = __h; \ + _key = __key; #define ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, _h, _val) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; \ + _h = __h; \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_NUM_KEY_VAL(ht, _h, _val) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _h = _p->h; \ + _h = __h; \ _val = _z; #define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val) \ ZEND_HASH_FOREACH(ht, 0); \ - _key = _p->key; \ + _key = __key; \ _val = _z; #define ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(ht, _key, _val, _from) \ ZEND_HASH_FOREACH_FROM(ht, 0, _from); \ - _key = _p->key; \ + _key = __key; \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(ht, _key, _val) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _key = _p->key; \ + _key = __key; \ _val = _z; #define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; \ - _key = _p->key; \ + _h = __h; \ + _key = __key; \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_KEY_VAL(ht, _h, _key, _val) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _h = _p->h; \ - _key = _p->key; \ + _h = __h; \ + _key = __key; \ _val = _z; #define ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \ ZEND_HASH_FOREACH(ht, 1); \ - _key = _p->key; \ + _key = __key; \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \ ZEND_HASH_REVERSE_FOREACH(ht, 1); \ - _key = _p->key; \ + _key = __key; \ _val = _z; #define ZEND_HASH_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ ZEND_HASH_FOREACH(ht, 1); \ - _h = _p->h; \ - _key = _p->key; \ + _h = __h; \ + _key = __key; \ _val = _z; #define ZEND_HASH_REVERSE_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ ZEND_HASH_REVERSE_FOREACH(ht, 1); \ - _h = _p->h; \ - _key = _p->key; \ + _h = __h; \ + _key = __key; \ _val = _z; #define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; \ + _h = __h; \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_REVERSE_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _h = _p->h; \ + _h = __h; \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \ ZEND_HASH_FOREACH(ht, 0); \ - _key = _p->key; \ + _key = __key; \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_REVERSE_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ - _key = _p->key; \ + _key = __key; \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \ ZEND_HASH_FOREACH(ht, 0); \ - _h = _p->h; \ - _key = _p->key; \ + _h = __h; \ + _key = __key; \ _ptr = Z_PTR_P(_z); #define ZEND_HASH_REVERSE_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \ ZEND_HASH_REVERSE_FOREACH(ht, 0); \ + _h = __h; \ + _key = __key; \ + _ptr = Z_PTR_P(_z); + +/* Hash array iterators */ +#define ZEND_HASH_MAP_FOREACH_FROM(_ht, indirect, _from) do { \ + HashTable *__ht = (_ht); \ + Bucket *_p = __ht->arData + (_from); \ + Bucket *_end = __ht->arData + __ht->nNumUsed; \ + ZEND_ASSERT(!HT_IS_PACKED(__ht)); \ + for (; _p != _end; _p++) { \ + zval *_z = &_p->val; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ + _z = Z_INDIRECT_P(_z); \ + } \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + +#define ZEND_HASH_MAP_FOREACH(_ht, indirect) ZEND_HASH_MAP_FOREACH_FROM(_ht, indirect, 0) + +#define ZEND_HASH_MAP_REVERSE_FOREACH(_ht, indirect) do { \ + HashTable *__ht = (_ht); \ + uint32_t _idx = __ht->nNumUsed; \ + Bucket *_p = __ht->arData + _idx; \ + zval *_z; \ + ZEND_ASSERT(!HT_IS_PACKED(__ht)); \ + for (_idx = __ht->nNumUsed; _idx > 0; _idx--) { \ + _p--; \ + _z = &_p->val; \ + if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \ + _z = Z_INDIRECT_P(_z); \ + } \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + +#define ZEND_HASH_MAP_FOREACH_END_DEL() \ + ZEND_ASSERT(!HT_IS_PACKED(__ht)); \ + __ht->nNumOfElements--; \ + do { \ + uint32_t j = HT_IDX_TO_HASH(_idx - 1); \ + uint32_t nIndex = _p->h | __ht->nTableMask; \ + uint32_t i = HT_HASH(__ht, nIndex); \ + if (UNEXPECTED(j != i)) { \ + Bucket *prev = HT_HASH_TO_BUCKET(__ht, i); \ + while (Z_NEXT(prev->val) != j) { \ + i = Z_NEXT(prev->val); \ + prev = HT_HASH_TO_BUCKET(__ht, i); \ + } \ + Z_NEXT(prev->val) = Z_NEXT(_p->val); \ + } else { \ + HT_HASH(__ht, nIndex) = Z_NEXT(_p->val); \ + } \ + } while (0); \ + } \ + __ht->nNumUsed = _idx; \ + } while (0) + +#define ZEND_HASH_MAP_FOREACH_BUCKET(ht, _bucket) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _bucket = _p; + +#define ZEND_HASH_MAP_FOREACH_BUCKET_FROM(ht, _bucket, _from) \ + ZEND_HASH_MAP_FOREACH_FROM(ht, 0, _from); \ + _bucket = _p; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_BUCKET(ht, _bucket) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _bucket = _p; + +#define ZEND_HASH_MAP_FOREACH_VAL(ht, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_VAL(ht, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_VAL_IND(ht, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 1); \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_VAL_IND(ht, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 1); \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_FOREACH_PTR_FROM(ht, _ptr, _from) \ + ZEND_HASH_MAP_FOREACH_FROM(ht, 0, _from); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_REVERSE_FOREACH_PTR(ht, _ptr) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_FOREACH_NUM_KEY(ht, _h) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_NUM_KEY(ht, _h) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; + +#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _key = _p->key; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY(ht, _key) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _key = _p->key; + +#define ZEND_HASH_MAP_FOREACH_KEY(ht, _h, _key) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_KEY(ht, _h, _key) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; + +#define ZEND_HASH_MAP_FOREACH_NUM_KEY_VAL(ht, _h, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_NUM_KEY_VAL(ht, _h, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht, _key, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_STR_KEY_VAL_FROM(ht, _key, _val, _from) \ + ZEND_HASH_MAP_FOREACH_FROM(ht, 0, _from); \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(ht, _key, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_KEY_VAL(ht, _h, _key, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_KEY_VAL(ht, _h, _key, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 1); \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL_IND(ht, _key, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 1); \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ + ZEND_HASH_MAP_FOREACH(ht, 1); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_REVERSE_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 1); \ + _h = _p->h; \ + _key = _p->key; \ + _val = _z; + +#define ZEND_HASH_MAP_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_REVERSE_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _h = _p->h; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _key = _p->key; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ + _key = _p->key; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \ + ZEND_HASH_MAP_FOREACH(ht, 0); \ + _h = _p->h; \ + _key = _p->key; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_MAP_REVERSE_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \ + ZEND_HASH_MAP_REVERSE_FOREACH(ht, 0); \ _h = _p->h; \ _key = _p->key; \ _ptr = Z_PTR_P(_z); +/* Packed array iterators */ +#define ZEND_HASH_PACKED_FOREACH_FROM(_ht, _from) do { \ + HashTable *__ht = (_ht); \ + zend_ulong _idx = (_from); \ + zval *_z = __ht->arPacked + (_from); \ + zval *_end = __ht->arPacked + __ht->nNumUsed; \ + ZEND_ASSERT(HT_IS_PACKED(__ht)); \ + for (;_z != _end; _z++, _idx++) { \ + (void) _idx; \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + +#define ZEND_HASH_PACKED_FOREACH(_ht) ZEND_HASH_PACKED_FOREACH_FROM(_ht, 0) + +#define ZEND_HASH_PACKED_REVERSE_FOREACH(_ht) do { \ + HashTable *__ht = (_ht); \ + zend_ulong _idx = __ht->nNumUsed; \ + zval *_z = __ht->arPacked + _idx; \ + ZEND_ASSERT(HT_IS_PACKED(__ht)); \ + while (_idx > 0) { \ + _z--; \ + _idx--; \ + (void) _idx; \ + if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue; + +#define ZEND_HASH_PACKED_FOREACH_VAL(ht, _val) \ + ZEND_HASH_PACKED_FOREACH(ht); \ + _val = _z; + +#define ZEND_HASH_PACKED_REVERSE_FOREACH_VAL(ht, _val) \ + ZEND_HASH_PACKED_REVERSE_FOREACH(ht); \ + _val = _z; + +#define ZEND_HASH_PACKED_FOREACH_PTR(ht, _ptr) \ + ZEND_HASH_PACKED_FOREACH(ht); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_PACKED_REVERSE_FOREACH_PTR(ht, _ptr) \ + ZEND_HASH_PACKED_REVERSE_FOREACH(ht); \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_PACKED_FOREACH_KEY(ht, _h) \ + ZEND_HASH_PACKED_FOREACH(ht); \ + _h = _idx; + +#define ZEND_HASH_PACKED_REVERSE_FOREACH_KEY(ht, _h) \ + ZEND_HASH_PACKED_REVERSE_FOREACH(ht); \ + _h = _idx; + +#define ZEND_HASH_PACKED_FOREACH_KEY_VAL(ht, _h, _val) \ + ZEND_HASH_PACKED_FOREACH(ht); \ + _h = _idx; \ + _val = _z; + +#define ZEND_HASH_PACKED_REVERSE_FOREACH_KEY_VAL(ht, _h, _val) \ + ZEND_HASH_PACKED_REVERSE_FOREACH(ht); \ + _h = _idx; \ + _val = _z; + +#define ZEND_HASH_PACKED_FOREACH_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_PACKED_FOREACH(ht); \ + _h = _idx; \ + _ptr = Z_PTR_P(_z); + +#define ZEND_HASH_PACKED_REVERSE_FOREACH_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_PACKED_REVERSE_FOREACH(ht); \ + _h = _idx; \ + _ptr = Z_PTR_P(_z); + /* The following macros are useful to insert a sequence of new elements * of packed array. They may be used instead of series of * zend_hash_next_index_insert_new() @@ -1173,7 +1496,7 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, */ #define ZEND_HASH_FILL_PACKED(ht) do { \ HashTable *__fill_ht = (ht); \ - Bucket *__fill_bkt = __fill_ht->arData + __fill_ht->nNumUsed; \ + zval *__fill_val = __fill_ht->arPacked + __fill_ht->nNumUsed; \ uint32_t __fill_idx = __fill_ht->nNumUsed; \ ZEND_ASSERT(HT_FLAGS(__fill_ht) & HASH_FLAG_PACKED); @@ -1183,35 +1506,33 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, __fill_ht->nNumOfElements = __fill_idx; \ __fill_ht->nNextFreeElement = __fill_idx; \ zend_hash_packed_grow(__fill_ht); \ - __fill_bkt = __fill_ht->arData + __fill_idx; \ + __fill_val = __fill_ht->arPacked + __fill_idx; \ } \ } while (0); #define ZEND_HASH_FILL_SET(_val) \ - ZVAL_COPY_VALUE(&__fill_bkt->val, _val) + ZVAL_COPY_VALUE(__fill_val, _val) #define ZEND_HASH_FILL_SET_NULL() \ - ZVAL_NULL(&__fill_bkt->val) + ZVAL_NULL(__fill_val) #define ZEND_HASH_FILL_SET_LONG(_val) \ - ZVAL_LONG(&__fill_bkt->val, _val) + ZVAL_LONG(__fill_val, _val) #define ZEND_HASH_FILL_SET_DOUBLE(_val) \ - ZVAL_DOUBLE(&__fill_bkt->val, _val) + ZVAL_DOUBLE(__fill_val, _val) #define ZEND_HASH_FILL_SET_STR(_val) \ - ZVAL_STR(&__fill_bkt->val, _val) + ZVAL_STR(__fill_val, _val) #define ZEND_HASH_FILL_SET_STR_COPY(_val) \ - ZVAL_STR_COPY(&__fill_bkt->val, _val) + ZVAL_STR_COPY(__fill_val, _val) #define ZEND_HASH_FILL_SET_INTERNED_STR(_val) \ - ZVAL_INTERNED_STR(&__fill_bkt->val, _val) + ZVAL_INTERNED_STR(__fill_val, _val) #define ZEND_HASH_FILL_NEXT() do {\ - __fill_bkt->h = (__fill_idx); \ - __fill_bkt->key = NULL; \ - __fill_bkt++; \ + __fill_val++; \ __fill_idx++; \ } while (0) @@ -1243,16 +1564,24 @@ static zend_always_inline bool zend_array_is_list(zend_array *array) } /* Packed arrays are lists */ - if (HT_IS_PACKED(array) && HT_IS_WITHOUT_HOLES(array)) { - return 1; - } - - /* Check if the list could theoretically be repacked */ - ZEND_HASH_FOREACH_KEY(array, num_idx, str_idx) { - if (str_idx != NULL || num_idx != expected_idx++) { - return 0; + if (HT_IS_PACKED(array)) { + if (HT_IS_WITHOUT_HOLES(array)) { + return 1; } - } ZEND_HASH_FOREACH_END(); + /* Check if the list could theoretically be repacked */ + ZEND_HASH_PACKED_FOREACH_KEY(array, num_idx) { + if (num_idx != expected_idx++) { + return 0; + } + } ZEND_HASH_FOREACH_END(); + } else { + /* Check if the list could theoretically be repacked */ + ZEND_HASH_MAP_FOREACH_KEY(array, num_idx, str_idx) { + if (str_idx != NULL || num_idx != expected_idx++) { + return 0; + } + } ZEND_HASH_FOREACH_END(); + } return 1; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0e8e1aa4627a7..ffb8fbe9e6553 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -979,7 +979,7 @@ static void ZEND_COLD emit_incompatible_method_error( if (status == INHERITANCE_UNRESOLVED) { /* Fetch the first unresolved class from registered autoloads */ zend_string *unresolved_class = NULL; - ZEND_HASH_FOREACH_STR_KEY(CG(delayed_autoloads), unresolved_class) { + ZEND_HASH_MAP_FOREACH_STR_KEY(CG(delayed_autoloads), unresolved_class) { break; } ZEND_HASH_FOREACH_END(); ZEND_ASSERT(unresolved_class); @@ -1397,7 +1397,7 @@ void zend_build_properties_info_table(zend_class_entry *ce) } } - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) { table[OBJ_PROP_TO_NUM(prop->offset)] = prop; } @@ -1529,7 +1529,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par } } - ZEND_HASH_FOREACH_PTR(&ce->properties_info, property_info) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property_info) { if (property_info->ce == ce) { if (property_info->flags & ZEND_ACC_STATIC) { property_info->offset += parent_ce->default_static_members_count; @@ -1544,7 +1544,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par zend_hash_num_elements(&ce->properties_info) + zend_hash_num_elements(&parent_ce->properties_info), 0); - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) { do_inherit_property(property_info, key, ce); } ZEND_HASH_FOREACH_END(); } @@ -1556,7 +1556,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par zend_hash_num_elements(&ce->constants_table) + zend_hash_num_elements(&parent_ce->constants_table), 0); - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) { do_inherit_class_constant(key, c, ce); } ZEND_HASH_FOREACH_END(); } @@ -1567,11 +1567,11 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par zend_hash_num_elements(&parent_ce->function_table), 0); if (checked) { - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { do_inherit_method(key, func, ce, 0, 1); } ZEND_HASH_FOREACH_END(); } else { - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { do_inherit_method(key, func, ce, 0, 0); } ZEND_HASH_FOREACH_END(); } @@ -1649,11 +1649,11 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * zend_string *key; zend_class_constant *c; - ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { do_inherit_iface_constant(key, c, ce, iface); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { do_inherit_method(key, func, ce, 1, 0); } ZEND_HASH_FOREACH_END(); @@ -1688,7 +1688,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } if (ignore) { /* Check for attempt to redeclare interface constants */ - ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { do_inherit_constant_check(ce, c, key); } ZEND_HASH_FOREACH_END(); } else { @@ -1733,7 +1733,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry return; } /* skip duplications */ - ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { do_inherit_constant_check(ce, c, key); } ZEND_HASH_FOREACH_END(); @@ -2104,7 +2104,7 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry for (i = 0; i < ce->num_traits; i++) { if (traits[i]) { /* copies functions, applies defined aliasing, and excludes unused trait methods */ - ZEND_HASH_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { zend_traits_copy_functions(key, fn, ce, exclude_tables[i], aliases); } ZEND_HASH_FOREACH_END(); @@ -2118,14 +2118,14 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry } else { for (i = 0; i < ce->num_traits; i++) { if (traits[i]) { - ZEND_HASH_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) { zend_traits_copy_functions(key, fn, ce, NULL, aliases); } ZEND_HASH_FOREACH_END(); } } } - ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { zend_fixup_trait_method(fn, ce); } ZEND_HASH_FOREACH_END(); } @@ -2168,7 +2168,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent if (!traits[i]) { continue; } - ZEND_HASH_FOREACH_STR_KEY_PTR(&traits[i]->properties_info, prop_name, property_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->properties_info, prop_name, property_info) { uint32_t flags = property_info->flags; /* next: check for conflicts with current class */ @@ -2313,7 +2313,7 @@ void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */ bool is_explicit_abstract = (ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) != 0; memset(&ai, 0, sizeof(ai)); - ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, func) { if (func->common.fn_flags & ZEND_ACC_ABSTRACT) { /* If the class is explicitly abstract, we only check private abstract methods, * because only they must be declared in the same class. */ @@ -2492,7 +2492,7 @@ static void load_delayed_classes(zend_class_entry *ce) { /* Take ownership of this HT, to avoid concurrent modification during autoloading. */ CG(delayed_autoloads) = NULL; - ZEND_HASH_FOREACH_STR_KEY(delayed_autoloads, name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(delayed_autoloads, name) { zend_lookup_class(name); if (EG(exception)) { zend_exception_uncaught_error( @@ -2530,7 +2530,7 @@ static void report_variance_errors(zend_class_entry *ce) { obligations = zend_hash_index_find_ptr(all_obligations, num_key); ZEND_ASSERT(obligations != NULL); - ZEND_HASH_FOREACH_PTR(obligations, obligation) { + ZEND_HASH_PACKED_FOREACH_PTR(obligations, obligation) { if (obligation->type == OBLIGATION_COMPATIBILITY) { /* Just used to populate the delayed_autoloads table, * which will be used when printing the "unresolved" error. */ @@ -2953,7 +2953,7 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e zend_property_info *parent_info; inheritance_status overall_status = INHERITANCE_SUCCESS; - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) { zval *zv = zend_hash_find_known_hash(&ce->function_table, key); if (zv) { zend_function *child_func = Z_FUNC_P(zv); @@ -2970,7 +2970,7 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, parent_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, parent_info) { zval *zv; if ((parent_info->flags & ZEND_ACC_PRIVATE) || !ZEND_TYPE_IS_SET(parent_info->type)) { continue; diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 59c8184381862..3ce92cc509523 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -125,7 +125,7 @@ ZEND_API void zend_ini_deactivate(void) /* {{{ */ if (EG(modified_ini_directives)) { zend_ini_entry *ini_entry; - ZEND_HASH_FOREACH_PTR(EG(modified_ini_directives), ini_entry) { + ZEND_HASH_MAP_FOREACH_PTR(EG(modified_ini_directives), ini_entry) { zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(EG(modified_ini_directives)); @@ -266,7 +266,7 @@ ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */ { zend_ini_entry *p; - ZEND_HASH_FOREACH_PTR(EG(ini_directives), p) { + ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), p) { if (p->on_modify) { p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage); } diff --git a/Zend/zend_list.c b/Zend/zend_list.c index b3409e33ce845..51ef3e1d92eb3 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -216,10 +216,11 @@ void zend_close_rsrc_list(HashTable *ht) { /* Reload ht->arData on each iteration, as it may be reallocated. */ uint32_t i = ht->nNumUsed; + while (i-- > 0) { - Bucket *p = &ht->arData[i]; - if (Z_TYPE(p->val) != IS_UNDEF) { - zend_resource *res = Z_PTR(p->val); + zval *p = ZEND_HASH_ELEMENT(ht, i); + if (Z_TYPE_P(p) != IS_UNDEF) { + zend_resource *res = Z_PTR_P(p); if (res->type >= 0) { zend_resource_dtor(res); } @@ -284,7 +285,7 @@ ZEND_API int zend_fetch_list_dtor_id(const char *type_name) { zend_rsrc_list_dtors_entry *lde; - ZEND_HASH_FOREACH_PTR(&list_destructors, lde) { + ZEND_HASH_PACKED_FOREACH_PTR(&list_destructors, lde) { if (lde->type_name && (strcmp(type_name, lde->type_name) == 0)) { return lde->resource_id; } diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 7e3fa03912a87..b09ce3b990d5c 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -238,7 +238,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, HT_FLAGS(new_object->properties) |= HT_FLAGS(old_object->properties) & HASH_FLAG_HAS_EMPTY_IND; - ZEND_HASH_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) { + ZEND_HASH_MAP_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) { if (Z_TYPE_P(prop) == IS_INDIRECT) { ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table)); } else { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ad41b9f699d01..566595783005e 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -249,7 +249,7 @@ ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce) if (constants_table && constants_table != &ce->constants_table) { zend_class_constant *c; - ZEND_HASH_FOREACH_PTR(constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(constants_table, c) { zval_ptr_dtor_nogc(&c->value); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(constants_table); @@ -285,7 +285,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_class_constant *c; zval *p, *end; - ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { if (c->ce == ce) { zval_ptr_dtor_nogc(&c->value); } @@ -362,7 +362,7 @@ ZEND_API void destroy_zend_class(zval *zv) } efree(ce->default_static_members_table); } - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop_info) { if (prop_info->ce == ce) { zend_string_release_ex(prop_info->name, 0); if (prop_info->doc_comment) { @@ -379,7 +379,7 @@ ZEND_API void destroy_zend_class(zval *zv) if (zend_hash_num_elements(&ce->constants_table)) { zend_class_constant *c; - ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { if (c->ce == ce) { zval_ptr_dtor_nogc(&c->value); if (c->doc_comment) { @@ -421,7 +421,7 @@ ZEND_API void destroy_zend_class(zval *zv) free(ce->default_static_members_table); } - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop_info) { if (prop_info->ce == ce) { zend_string_release(prop_info->name); zend_type_release(prop_info->type, /* persistent */ 1); @@ -432,7 +432,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_string_release_ex(ce->name, 1); /* TODO: eliminate this loop for classes without functions with arg_info */ - ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) { if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && fn->common.scope == ce) { zend_free_internal_arg_info(&fn->internal_function); @@ -443,7 +443,7 @@ ZEND_API void destroy_zend_class(zval *zv) if (zend_hash_num_elements(&ce->constants_table)) { zend_class_constant *c; - ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { if (c->ce == ce) { if (Z_TYPE(c->value) == IS_CONSTANT_AST) { /* We marked this as IMMUTABLE, but do need to free it when the diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 4a1232198fcc2..c0efe2a6dcf4a 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -368,7 +368,11 @@ struct _zend_array { uint32_t flags; } u; uint32_t nTableMask; - Bucket *arData; + union { + uint32_t *arHash; /* hash table (allocated above this pointer) */ + Bucket *arData; /* array of hash buckets */ + zval *arPacked; /* packed array of zvals */ + }; uint32_t nNumUsed; uint32_t nNumOfElements; uint32_t nTableSize; @@ -382,14 +386,14 @@ struct _zend_array { * ===================== * * +=============================+ - * | HT_HASH(ht, ht->nTableMask) | - * | ... | - * | HT_HASH(ht, -1) | - * +-----------------------------+ - * ht->arData ---> | Bucket[0] | - * | ... | - * | Bucket[ht->nTableSize-1] | - * +=============================+ + * | HT_HASH(ht, ht->nTableMask) | +=============================+ + * | ... | | HT_INVALID_IDX | + * | HT_HASH(ht, -1) | | HT_INVALID_IDX | + * +-----------------------------+ +-----------------------------+ + * ht->arData ---> | Bucket[0] | ht->arPacked ---> | ZVAL[0] | + * | ... | | ... | + * | Bucket[ht->nTableSize-1] | | ZVAL[ht->nTableSize-1] | + * +=============================+ +=============================+ */ #define HT_INVALID_IDX ((uint32_t) -1) @@ -420,7 +424,7 @@ struct _zend_array { #define HT_HASH_EX(data, idx) \ ((uint32_t*)(data))[(int32_t)(idx)] #define HT_HASH(ht, idx) \ - HT_HASH_EX((ht)->arData, idx) + HT_HASH_EX((ht)->arHash, idx) #define HT_SIZE_TO_MASK(nTableSize) \ ((uint32_t)(-((nTableSize) + (nTableSize)))) @@ -434,6 +438,14 @@ struct _zend_array { HT_SIZE_EX((ht)->nTableSize, (ht)->nTableMask) #define HT_USED_SIZE(ht) \ (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(Bucket))) +#define HT_PACKED_DATA_SIZE(nTableSize) \ + ((size_t)(nTableSize) * sizeof(zval)) +#define HT_PACKED_SIZE_EX(nTableSize, nTableMask) \ + (HT_PACKED_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask))) +#define HT_PACKED_SIZE(ht) \ + HT_PACKED_SIZE_EX((ht)->nTableSize, (ht)->nTableMask) +#define HT_PACKED_USED_SIZE(ht) \ + (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(zval))) #ifdef __SSE2__ # define HT_HASH_RESET(ht) do { \ char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ae8b647f7f352..9979a9b2fb515 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5559,7 +5559,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args]; if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); - ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } @@ -5571,7 +5571,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) ZVAL_ARR(params, EX(extra_named_params)); } else { SEPARATE_ARRAY(params); - ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { Z_TRY_ADDREF_P(param); zend_hash_add_new(Z_ARRVAL_P(params), name, param); } ZEND_HASH_FOREACH_END(); @@ -6830,7 +6830,6 @@ ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR) uint32_t value_type; HashTable *fe_ht; HashPosition pos; - Bucket *p; array = EX_VAR(opline->op1.var); if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) { @@ -6838,31 +6837,54 @@ ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR) } fe_ht = Z_ARRVAL_P(array); pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - Z_FE_POS_P(array) = pos; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } - if (EXPECTED(OP2_TYPE == IS_CV)) { zval *variable_ptr = EX_VAR(opline->op2.var); SAVE_OPLINE(); @@ -6897,27 +6919,48 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); fe_ht = Z_ARRVAL_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_C_GOTO(fe_fetch_w_exit); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_C_GOTO(fe_fetch_w_exit); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_C_GOTO(fe_fetch_w_exit); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -9000,7 +9043,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM } SAVE_OPLINE(); - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { FREE_OP1(); @@ -9745,34 +9788,57 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FE_FETCH_R, op->op2_type == IS_CV && (op1_inf uint32_t value_type; HashTable *fe_ht; HashPosition pos; - Bucket *p; array = EX_VAR(opline->op1.var); SAVE_OPLINE(); fe_ht = Z_ARRVAL_P(array); pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - Z_FE_POS_P(array) = pos; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d25c9e687c02d..4a26e0c252e35 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3848,7 +3848,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args]; if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); - ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } @@ -3860,7 +3860,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND ZVAL_ARR(params, EX(extra_named_params)); } else { SEPARATE_ARRAY(params); - ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { Z_TRY_ADDREF_P(param); zend_hash_add_new(Z_ARRVAL_P(params), name, param); } ZEND_HASH_FOREACH_END(); @@ -7682,7 +7682,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON } SAVE_OPLINE(); - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { @@ -19908,7 +19908,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLE } SAVE_OPLINE(); - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -21882,7 +21882,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VA uint32_t value_type; HashTable *fe_ht; HashPosition pos; - Bucket *p; array = EX_VAR(opline->op1.var); if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) { @@ -21890,31 +21889,54 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VA } fe_ht = Z_ARRVAL_P(array); pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - Z_FE_POS_P(array) = pos; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } - if (EXPECTED(opline->op2_type == IS_CV)) { zval *variable_ptr = EX_VAR(opline->op2.var); SAVE_OPLINE(); @@ -21949,27 +21971,48 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); fe_ht = Z_ARRVAL_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - goto fe_fetch_w_exit; + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; - if (RETURN_VALUE_USED(opline)) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -24841,7 +24884,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLE } SAVE_OPLINE(); - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -30942,34 +30985,57 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ uint32_t value_type; HashTable *fe_ht; HashPosition pos; - Bucket *p; array = EX_VAR(opline->op1.var); SAVE_OPLINE(); fe_ht = Z_ARRVAL_P(array); pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + Z_FE_POS_P(array) = pos + 1; + if (0) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - Z_FE_POS_P(array) = pos; - if (0) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (0) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } @@ -30987,34 +31053,57 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ uint32_t value_type; HashTable *fe_ht; HashPosition pos; - Bucket *p; array = EX_VAR(opline->op1.var); SAVE_OPLINE(); fe_ht = Z_ARRVAL_P(array); pos = Z_FE_POS_P(array); - p = fe_ht->arData + pos; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - /* reached end of iteration */ - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; } - pos++; - value = &p->val; - value_type = Z_TYPE_INFO_P(value); - ZEND_ASSERT(value_type != IS_INDIRECT); - if (EXPECTED(value_type != IS_UNDEF)) { - break; + Z_FE_POS_P(array) = pos + 1; + if (1) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); } - p++; - } - Z_FE_POS_P(array) = pos; - if (1) { - if (!p->key) { - ZVAL_LONG(EX_VAR(opline->result.var), p->h); - } else { - ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (1) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } } } @@ -42422,7 +42511,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER } SAVE_OPLINE(); - ZEND_HASH_FOREACH_STR_KEY(ht, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { diff --git a/Zend/zend_vm_trace_handlers.h b/Zend/zend_vm_trace_handlers.h index 414d4d5f95f67..eaf97e012cac7 100644 --- a/Zend/zend_vm_trace_handlers.h +++ b/Zend/zend_vm_trace_handlers.h @@ -71,7 +71,7 @@ static void zend_vm_trace_finish(void) f = fopen("zend_vm_trace.log", "w+"); if (f) { zend_hash_sort(&vm_trace_ht, (compare_func_t)zend_vm_trace_compare, 0); - ZEND_HASH_FOREACH_STR_KEY_VAL(&vm_trace_ht, key, val) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&vm_trace_ht, key, val) { fprintf(f, "%s "ZEND_LONG_FMT"\n", ZSTR_VAL(key), Z_LVAL_P(val)); } ZEND_HASH_FOREACH_END(); fclose(f); diff --git a/Zend/zend_vm_trace_map.h b/Zend/zend_vm_trace_map.h index 96695312a93d0..d84aa0442d263 100644 --- a/Zend/zend_vm_trace_map.h +++ b/Zend/zend_vm_trace_map.h @@ -65,7 +65,7 @@ static void zend_vm_trace_init(void) if (f) { zend_hash_sort(&vm_trace_ht, (bucket_compare_func_t)zend_vm_trace_compare, 0); prev_key = NULL; - ZEND_HASH_FOREACH_STR_KEY_VAL(&vm_trace_ht, key, val) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&vm_trace_ht, key, val) { if (prev_key) { fprintf(f, ADDR_FMT" "ADDR_FMT" t %s\n", prev_addr, Z_LVAL_P(val) - prev_addr, ZSTR_VAL(prev_key)); } diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index aa6114fa6d8d6..e5f8a4b220de8 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -72,7 +72,7 @@ static void zend_weakref_unref(zend_ulong obj_addr, void *tagged_ptr) { uintptr_t tag = ZEND_WEAKREF_GET_TAG(tagged_ptr); if (tag == ZEND_WEAKREF_TAG_HT) { HashTable *ht = ptr; - ZEND_HASH_FOREACH_PTR(ht, tagged_ptr) { + ZEND_HASH_MAP_FOREACH_PTR(ht, tagged_ptr) { zend_weakref_unref_single( ZEND_WEAKREF_GET_PTR(tagged_ptr), ZEND_WEAKREF_GET_TAG(tagged_ptr), obj_addr); } ZEND_HASH_FOREACH_END(); @@ -209,7 +209,7 @@ static zend_always_inline bool zend_weakref_find(zend_object *referent, zval *re } if (tag == ZEND_WEAKREF_TAG_HT) { - ZEND_HASH_FOREACH(ptr, tagged_ptr) { + ZEND_HASH_MAP_FOREACH(ptr, tagged_ptr) { if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_REF) { ptr = ZEND_WEAKREF_GET_PTR(tagged_ptr); goto found_weakref; @@ -290,7 +290,7 @@ static void zend_weakmap_free_obj(zend_object *object) { zend_weakmap *wm = zend_weakmap_from(object); zend_ulong obj_addr; - ZEND_HASH_FOREACH_NUM_KEY(&wm->ht, obj_addr) { + ZEND_HASH_MAP_FOREACH_NUM_KEY(&wm->ht, obj_addr) { zend_weakref_unregister( (zend_object *) obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP)); } ZEND_HASH_FOREACH_END(); @@ -412,7 +412,7 @@ static HashTable *zend_weakmap_get_properties_for(zend_object *object, zend_prop zend_ulong obj_addr; zval *val; - ZEND_HASH_FOREACH_NUM_KEY_VAL(&wm->ht, obj_addr, val) { + ZEND_HASH_MAP_FOREACH_NUM_KEY_VAL(&wm->ht, obj_addr, val) { zend_object *obj = (zend_object*)obj_addr; zval pair; array_init(&pair); @@ -433,7 +433,7 @@ static HashTable *zend_weakmap_get_gc(zend_object *object, zval **table, int *n) zend_weakmap *wm = zend_weakmap_from(object); zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); zval *val; - ZEND_HASH_FOREACH_VAL(&wm->ht, val) { + ZEND_HASH_MAP_FOREACH_VAL(&wm->ht, val) { zend_get_gc_buffer_add_zval(gc_buffer, val); } ZEND_HASH_FOREACH_END(); zend_get_gc_buffer_use(gc_buffer, table, n); @@ -449,7 +449,7 @@ static zend_object *zend_weakmap_clone_obj(zend_object *old_object) zend_ulong obj_addr; zval *val; - ZEND_HASH_FOREACH_NUM_KEY_VAL(&new_wm->ht, obj_addr, val) { + ZEND_HASH_MAP_FOREACH_NUM_KEY_VAL(&new_wm->ht, obj_addr, val) { zend_weakref_register( (zend_object *) obj_addr, ZEND_WEAKREF_ENCODE(new_wm, ZEND_WEAKREF_TAG_MAP)); zval_add_ref(val); diff --git a/ext/dom/node.c b/ext/dom/node.c index 893670807bca4..fc1b725bb28ae 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -1592,11 +1592,11 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ ctxp->node = nodep; tmp = zend_hash_str_find(ht, "namespaces", sizeof("namespaces")-1); - if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) { + if (tmp && Z_TYPE_P(tmp) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(tmp))) { zval *tmpns; zend_string *prefix; - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) { if (Z_TYPE_P(tmpns) == IS_STRING) { if (prefix) { xmlXPathRegisterNs(ctxp, (xmlChar *) ZSTR_VAL(prefix), (xmlChar *) Z_STRVAL_P(tmpns)); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 01a206c0985bd..f9e7f2e0b45ee 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -405,7 +405,7 @@ static HashTable* dom_get_debug_info_helper(zend_object *object, int *is_temp) / object_str = zend_string_init("(object value omitted)", sizeof("(object value omitted)")-1, 0); - ZEND_HASH_FOREACH_STR_KEY_PTR(prop_handlers, string_key, entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(prop_handlers, string_key, entry) { zval value; if (entry->read_func(obj, &value) == FAILURE || !string_key) { diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index e108ca61be6f5..352a732a49626 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -296,7 +296,7 @@ static ffi_type* zend_ffi_face_struct_add_fields(ffi_type* t, zend_ffi_type *typ { zend_ffi_field *field; - ZEND_HASH_FOREACH_PTR(&type->record.fields, field) { + ZEND_HASH_MAP_FOREACH_PTR(&type->record.fields, field) { switch (ZEND_FFI_TYPE(field->type)->kind) { case ZEND_FFI_TYPE_FLOAT: t->elements[(*i)++] = &ffi_type_float; @@ -811,7 +811,7 @@ static size_t zend_ffi_arg_size(zend_ffi_type *type) /* {{{ */ zend_ffi_type *arg_type; size_t arg_size = 0; - ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(type->func.args, arg_type) { arg_size += MAX(ZEND_FFI_TYPE(arg_type)->size, sizeof(size_t)); } ZEND_HASH_FOREACH_END(); return arg_size; @@ -885,7 +885,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v int n = 0; zend_ffi_type *arg_type; - ZEND_HASH_FOREACH_PTR(callback_data->type->func.args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(callback_data->type->func.args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); zend_ffi_cdata_to_zval(NULL, args[n], arg_type, BP_VAR_R, &fci.params[n], (zend_ffi_flags)(arg_type->attr & ZEND_FFI_ATTR_CONST), 0, 0); n++; @@ -959,7 +959,7 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ * int n = 0; zend_ffi_type *arg_type; - ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(type->func.args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); callback_data->arg_types[n] = zend_ffi_get_type(arg_type); if (!callback_data->arg_types[n]) { @@ -1991,7 +1991,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) break; case ZEND_FFI_TYPE_STRUCT: ht = zend_new_array(zend_hash_num_elements(&type->record.fields)); - ZEND_HASH_FOREACH_STR_KEY_PTR(&type->record.fields, key, f) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&type->record.fields, key, f) { if (key) { if (!f->bits) { void *f_ptr = (void*)(((char*)ptr) + f->offset); @@ -2652,7 +2652,7 @@ static ZEND_FUNCTION(ffi_trampoline) /* {{{ */ (sizeof(void*) + ZEND_FFI_SIZEOF_ARG) * EX_NUM_ARGS(), arg_values_use_heap); n = 0; if (type->func.args) { - ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(type->func.args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); arg_values[n] = ((char*)arg_values) + (sizeof(void*) * EX_NUM_ARGS()) + (ZEND_FFI_SIZEOF_ARG * n); if (zend_ffi_pass_arg(EX_VAR_NUM(n), arg_type, &arg_types[n], arg_values, n, execute_data) == FAILURE) { @@ -2697,7 +2697,7 @@ static ZEND_FUNCTION(ffi_trampoline) /* {{{ */ (sizeof(void*) + ZEND_FFI_SIZEOF_ARG) * EX_NUM_ARGS(), arg_values_use_heap); n = 0; if (type->func.args) { - ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(type->func.args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); arg_values[n] = ((char*)arg_values) + (sizeof(void*) * EX_NUM_ARGS()) + (ZEND_FFI_SIZEOF_ARG * n); if (zend_ffi_pass_arg(EX_VAR_NUM(n), arg_type, &arg_types[n], arg_values, n, execute_data) == FAILURE) { @@ -2903,7 +2903,7 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ zend_string *name; zend_ffi_symbol *sym; - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { if (sym->kind == ZEND_FFI_SYM_VAR) { addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); if (!addr) { @@ -2967,7 +2967,7 @@ static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ zend_string *key; Bucket *b = type->record.fields.arData; - ZEND_HASH_FOREACH_STR_KEY_PTR(&old->record.fields, key, old_field) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&old->record.fields, key, old_field) { while (Z_TYPE(b->val) == IS_UNDEF) { b++; } @@ -2999,16 +2999,16 @@ static bool zend_ffi_same_types(zend_ffi_type *old, zend_ffi_type *type) /* {{{ return 0; } else if (old->func.args) { zend_ffi_type *arg_type; - Bucket *b = type->func.args->arData; + zval *zv = type->func.args->arPacked; - ZEND_HASH_FOREACH_PTR(old->func.args, arg_type) { - while (Z_TYPE(b->val) == IS_UNDEF) { - b++; + ZEND_HASH_PACKED_FOREACH_PTR(old->func.args, arg_type) { + while (Z_TYPE_P(zv) == IS_UNDEF) { + zv++; } - if (!zend_ffi_same_types(ZEND_FFI_TYPE(arg_type), ZEND_FFI_TYPE(Z_PTR(b->val)))) { + if (!zend_ffi_same_types(ZEND_FFI_TYPE(arg_type), ZEND_FFI_TYPE(Z_PTR_P(zv)))) { return 0; } - b++; + zv++; } ZEND_HASH_FOREACH_END(); } break; @@ -3068,7 +3068,7 @@ static bool zend_ffi_subst_old_type(zend_ffi_type **dcl, zend_ffi_type *old, zen if (dcl_type->func.args) { zval *zv; - ZEND_HASH_FOREACH_VAL(dcl_type->func.args, zv) { + ZEND_HASH_PACKED_FOREACH_VAL(dcl_type->func.args, zv) { if (zend_ffi_subst_old_type((zend_ffi_type**)&Z_PTR_P(zv), old, type)) { return 1; } @@ -3076,7 +3076,7 @@ static bool zend_ffi_subst_old_type(zend_ffi_type **dcl, zend_ffi_type *old, zen } break; case ZEND_FFI_TYPE_STRUCT: - ZEND_HASH_FOREACH_PTR(&dcl_type->record.fields, field) { + ZEND_HASH_MAP_FOREACH_PTR(&dcl_type->record.fields, field) { if (zend_ffi_subst_old_type(&field->type, old, type)) { return 1; } @@ -3094,12 +3094,12 @@ static void zend_ffi_cleanup_type(zend_ffi_type *old, zend_ffi_type *type) /* {{ zend_ffi_tag *tag; if (FFI_G(symbols)) { - ZEND_HASH_FOREACH_PTR(FFI_G(symbols), sym) { + ZEND_HASH_MAP_FOREACH_PTR(FFI_G(symbols), sym) { zend_ffi_subst_old_type(&sym->type, old, type); } ZEND_HASH_FOREACH_END(); } if (FFI_G(tags)) { - ZEND_HASH_FOREACH_PTR(FFI_G(tags), tag) { + ZEND_HASH_MAP_FOREACH_PTR(FFI_G(tags), tag) { zend_ffi_subst_old_type(&tag->type, old, type); } ZEND_HASH_FOREACH_END(); } @@ -3222,7 +3222,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ } if (FFI_G(symbols)) { - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { if (sym->kind == ZEND_FFI_SYM_VAR) { addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); if (!addr) { @@ -3280,7 +3280,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ if (preload) { if (scope && scope->tags && FFI_G(tags)) { - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(tags), name, tag) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(tags), name, tag) { zend_ffi_tag *old_tag = zend_hash_find_ptr(scope->tags, name); if (old_tag) { @@ -3319,7 +3319,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ scope->symbols = FFI_G(symbols); FFI_G(symbols) = NULL; } else { - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), name, sym) { if (!zend_hash_add_ptr(scope->symbols, name, sym)) { zend_ffi_type_dtor(sym->type); free(sym); @@ -3334,7 +3334,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */ scope->tags = FFI_G(tags); FFI_G(tags) = NULL; } else { - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(tags), name, tag) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(tags), name, tag) { if (!zend_hash_add_ptr(scope->tags, name, tag)) { zend_ffi_type_dtor(tag->type); free(tag); @@ -3483,7 +3483,7 @@ static zend_result zend_ffi_validate_incomplete_type(zend_ffi_type *type, bool a zend_string *key; zend_ffi_tag *tag; - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(tags), key, tag) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(tags), key, tag) { if (ZEND_FFI_TYPE(tag->type) == type) { if (type->kind == ZEND_FFI_TYPE_ENUM) { zend_ffi_throw_parser_error("Incomplete enum \"%s\" at line %d", ZSTR_VAL(key), FFI_G(line)); @@ -3500,7 +3500,7 @@ static zend_result zend_ffi_validate_incomplete_type(zend_ffi_type *type, bool a zend_string *key; zend_ffi_symbol *sym; - ZEND_HASH_FOREACH_STR_KEY_PTR(FFI_G(symbols), key, sym) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(FFI_G(symbols), key, sym) { if (type == ZEND_FFI_TYPE(sym->type)) { zend_ffi_throw_parser_error("Incomplete C type %s at line %d", ZSTR_VAL(key), FFI_G(line)); return FAILURE; @@ -3572,7 +3572,7 @@ static bool zend_ffi_subst_type(zend_ffi_type **dcl, zend_ffi_type *type) /* {{{ if (dcl_type->func.args) { zval *zv; - ZEND_HASH_FOREACH_VAL(dcl_type->func.args, zv) { + ZEND_HASH_PACKED_FOREACH_VAL(dcl_type->func.args, zv) { if (zend_ffi_subst_type((zend_ffi_type**)&Z_PTR_P(zv), type)) { return 1; } @@ -3580,7 +3580,7 @@ static bool zend_ffi_subst_type(zend_ffi_type **dcl, zend_ffi_type *type) /* {{{ } break; case ZEND_FFI_TYPE_STRUCT: - ZEND_HASH_FOREACH_PTR(&dcl_type->record.fields, field) { + ZEND_HASH_MAP_FOREACH_PTR(&dcl_type->record.fields, field) { if (zend_ffi_subst_type(&field->type, type)) { return 1; } @@ -3595,7 +3595,7 @@ static bool zend_ffi_subst_type(zend_ffi_type **dcl, zend_ffi_type *type) /* {{{ static void zend_ffi_tags_cleanup(zend_ffi_dcl *dcl) /* {{{ */ { zend_ffi_tag *tag; - ZEND_HASH_FOREACH_PTR(FFI_G(tags), tag) { + ZEND_HASH_MAP_FOREACH_PTR(FFI_G(tags), tag) { if (ZEND_FFI_TYPE_IS_OWNED(tag->type)) { zend_ffi_type *type = ZEND_FFI_TYPE(tag->type); zend_ffi_subst_type(&dcl->type, type); @@ -4624,7 +4624,7 @@ ZEND_METHOD(FFI_CType, getStructFieldNames) /* {{{ */ ht = zend_new_array(zend_hash_num_elements(&type->record.fields)); RETVAL_ARR(ht); - ZEND_HASH_FOREACH_STR_KEY(&type->record.fields, name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&type->record.fields, name) { ZVAL_STR_COPY(&zv, name); zend_hash_next_index_insert_new(ht, &zv); } ZEND_HASH_FOREACH_END(); @@ -5901,7 +5901,7 @@ static zend_result zend_ffi_validate_prev_field_type(zend_ffi_type *struct_type) if (zend_hash_num_elements(&struct_type->record.fields) > 0) { zend_ffi_field *field = NULL; - ZEND_HASH_REVERSE_FOREACH_PTR(&struct_type->record.fields, field) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&struct_type->record.fields, field) { break; } ZEND_HASH_FOREACH_END(); if (ZEND_FFI_TYPE(field->type)->attr & ZEND_FFI_ATTR_INCOMPLETE_ARRAY) { @@ -6004,7 +6004,7 @@ void zend_ffi_add_anonymous_field(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_ } } - ZEND_HASH_FOREACH_STR_KEY_PTR(&field_type->record.fields, key, field) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&field_type->record.fields, key, field) { zend_ffi_field *new_field = pemalloc(sizeof(zend_ffi_field), FFI_G(persistent)); if (struct_type->attr & ZEND_FFI_ATTR_UNION) { @@ -6108,7 +6108,7 @@ void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t n zend_ffi_field *prev_field = NULL; if (zend_hash_num_elements(&struct_type->record.fields) > 0) { - ZEND_HASH_REVERSE_FOREACH_PTR(&struct_type->record.fields, prev_field) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&struct_type->record.fields, prev_field) { break; } ZEND_HASH_FOREACH_END(); } @@ -6264,7 +6264,7 @@ void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *n int no_args = 0; zend_ffi_type *arg_type; - ZEND_HASH_FOREACH_PTR(args, arg_type) { + ZEND_HASH_PACKED_FOREACH_PTR(args, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); if (arg_type->kind == ZEND_FFI_TYPE_VOID) { if (zend_hash_num_elements(args) != 1) { @@ -6291,7 +6291,7 @@ void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *n zend_ulong i; zend_ffi_type *arg_type; - ZEND_HASH_FOREACH_NUM_KEY_PTR(args, i, arg_type) { + ZEND_HASH_PACKED_FOREACH_KEY_PTR(args, i, arg_type) { arg_type = ZEND_FFI_TYPE(arg_type); # ifdef _WIN64 if (i >= 4 && i <= 5 && (arg_type->kind == ZEND_FFI_TYPE_FLOAT || arg_type->kind == ZEND_FFI_TYPE_DOUBLE)) { diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 880d6dddc7d70..d7b030d134535 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3233,15 +3233,17 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode) zend_string *key; /* walk the assoc array */ - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(EXT), key, item) { - if (key == NULL) { - continue; - } - if (zend_string_equals_literal(key, "linespacing")) { - strex.flags |= gdFTEX_LINESPACE; - strex.linespacing = zval_get_double(item); - } - } ZEND_HASH_FOREACH_END(); + if (!HT_IS_PACKED(Z_ARRVAL_P(EXT))) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(EXT), key, item) { + if (key == NULL) { + continue; + } + if (zend_string_equals_literal(key, "linespacing")) { + strex.flags |= gdFTEX_LINESPACE; + strex.linespacing = zval_get_double(item); + } + } ZEND_HASH_FOREACH_END(); + } } #ifdef VIRTUAL_DIR diff --git a/ext/hash/hash.c b/ext/hash/hash.c index a89939e634127..62b82263dc7e3 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -860,7 +860,7 @@ PHP_FUNCTION(hash_algos) } array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY(&php_hash_hashtable, str) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_hash_hashtable, str) { add_next_index_str(return_value, zend_string_copy(str)); } ZEND_HASH_FOREACH_END(); } @@ -877,7 +877,7 @@ PHP_FUNCTION(hash_hmac_algos) } array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(&php_hash_hashtable, str, ops) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&php_hash_hashtable, str, ops) { if (ops->is_crypto) { add_next_index_str(return_value, zend_string_copy(str)); } @@ -1663,7 +1663,7 @@ PHP_MINFO_FUNCTION(hash) zend_string *str; char *s = buffer, *e = s + sizeof(buffer); - ZEND_HASH_FOREACH_STR_KEY(&php_hash_hashtable, str) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_hash_hashtable, str) { s += slprintf(s, e - s, "%s ", ZSTR_VAL(str)); } ZEND_HASH_FOREACH_END(); *s = 0; diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index a543c1d78a21b..b6d2dd8b74da8 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -3193,10 +3193,10 @@ PHP_FUNCTION(imap_mail_compose) bod->parameter = tmp_param; } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) { - if(Z_TYPE_P(pvalue) == IS_ARRAY) { + if(Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) { disp_param = tmp_param = NULL; SEPARATE_ARRAY(pvalue); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { if (key == NULL) continue; CHECK_HEADER_INJECTION(key, 0, "body disposition key"); disp_param = mail_newbody_parameter(); @@ -3233,10 +3233,10 @@ PHP_FUNCTION(imap_mail_compose) memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1); } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) { - if (Z_TYPE_P(pvalue) == IS_ARRAY) { + if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) { disp_param = tmp_param = NULL; SEPARATE_ARRAY(pvalue); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { if (key == NULL) continue; CHECK_HEADER_INJECTION(key, 0, "body type.parameters key"); disp_param = mail_newbody_parameter(); @@ -3315,10 +3315,10 @@ PHP_FUNCTION(imap_mail_compose) bod->parameter = tmp_param; } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) { - if (Z_TYPE_P(pvalue) == IS_ARRAY) { + if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) { disp_param = tmp_param = NULL; SEPARATE_ARRAY(pvalue); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { if (key == NULL) continue; CHECK_HEADER_INJECTION(key, 0, "body type.parameters key"); disp_param = mail_newbody_parameter(); @@ -3355,10 +3355,10 @@ PHP_FUNCTION(imap_mail_compose) memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1); } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) { - if (Z_TYPE_P(pvalue) == IS_ARRAY) { + if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) { disp_param = tmp_param = NULL; SEPARATE_ARRAY(pvalue); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) { if (key == NULL) continue; CHECK_HEADER_INJECTION(key, 0, "body disposition key"); disp_param = mail_newbody_parameter(); diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 3782820e77d62..cf16f198a812c 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -398,7 +398,7 @@ HashTable *mysqli_object_get_debug_info(zend_object *object, int *is_temp) retval = zend_new_array(zend_hash_num_elements(props) + 1); - ZEND_HASH_FOREACH_PTR(props, entry) { + ZEND_HASH_MAP_FOREACH_PTR(props, entry) { zval rv; zval *value; diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c index 0d76d2e4f6af1..6a33a16892436 100644 --- a/ext/mysqlnd/mysqlnd_debug.c +++ b/ext/mysqlnd/mysqlnd_debug.c @@ -430,7 +430,7 @@ MYSQLND_METHOD(mysqlnd_debug, close)(MYSQLND_DEBUG * self) self->m->log_va(self, __LINE__, __FILE__, 0, "info : ", "number of functions: %d", zend_hash_num_elements(&self->function_profiles)); - ZEND_HASH_FOREACH_STR_KEY_PTR(&self->function_profiles, string_key, f_profile) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&self->function_profiles, string_key, f_profile) { self->m->log_va(self, __LINE__, __FILE__, -1, "info : ", "%-40s\tcalls=%5" PRIu64 " own_slow=%5" PRIu64 diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c index dad8187ba9646..4bd9894b8c4bb 100644 --- a/ext/mysqlnd/mysqlnd_plugin.c +++ b/ext/mysqlnd/mysqlnd_plugin.c @@ -167,7 +167,7 @@ PHPAPI void mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, void zval *val; int result; - ZEND_HASH_FOREACH_VAL(&mysqlnd_registered_plugins, val) { + ZEND_HASH_MAP_FOREACH_VAL(&mysqlnd_registered_plugins, val) { result = apply_func(val, argument); if (result & ZEND_HASH_APPLY_REMOVE) { php_error_docref(NULL, E_WARNING, "mysqlnd_plugin_apply_with_argument must not remove table entries"); diff --git a/ext/mysqlnd/mysqlnd_reverse_api.c b/ext/mysqlnd/mysqlnd_reverse_api.c index ae4b4e74c8031..982aac065eb04 100644 --- a/ext/mysqlnd/mysqlnd_reverse_api.c +++ b/ext/mysqlnd/mysqlnd_reverse_api.c @@ -67,7 +67,7 @@ PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities) { MYSQLND_REVERSE_API *api; - ZEND_HASH_FOREACH_PTR(&mysqlnd_api_ext_ht, api) { + ZEND_HASH_MAP_FOREACH_PTR(&mysqlnd_api_ext_ht, api) { if (api->conversion_cb) { MYSQLND *retval = api->conversion_cb(zv); if (retval) { diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 77d0c31aa6dda..644909cc4ba98 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -573,7 +573,7 @@ size_t php_mysqlnd_auth_write(MYSQLND_CONN_DATA * conn, void * _packet) { zend_string * key; zval * entry_value; - ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) { if (key) { /* HASH_KEY_IS_STRING */ size_t value_len = Z_STRLEN_P(entry_value); @@ -591,7 +591,7 @@ size_t php_mysqlnd_auth_write(MYSQLND_CONN_DATA * conn, void * _packet) { zend_string * key; zval * entry_value; - ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) { if (key) { /* HASH_KEY_IS_STRING */ size_t value_len = Z_STRLEN_P(entry_value); diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c index ff31a54b454f3..368c253a64f9f 100644 --- a/ext/mysqlnd/php_mysqlnd.c +++ b/ext/mysqlnd/php_mysqlnd.c @@ -31,7 +31,7 @@ mysqlnd_minfo_print_hash(zval *values) zval *values_entry; zend_string *string_key; - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(values), string_key, values_entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(values), string_key, values_entry) { convert_to_string(values_entry); php_info_print_table_row(2, ZSTR_VAL(string_key), Z_STRVAL_P(values_entry)); } ZEND_HASH_FOREACH_END(); @@ -63,7 +63,7 @@ mysqlnd_minfo_dump_api_plugins(smart_str * buffer) HashTable *ht = mysqlnd_reverse_api_get_api_list(); MYSQLND_REVERSE_API *ext; - ZEND_HASH_FOREACH_PTR(ht, ext) { + ZEND_HASH_MAP_FOREACH_PTR(ht, ext) { if (buffer->s) { smart_str_appendc(buffer, ','); } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 8fe2d271f7f49..e06d3ca67250f 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -601,7 +601,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } /* function table hash keys */ - ZEND_HASH_FOREACH_BUCKET(CG(function_table), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(CG(function_table), p) { if (p->key) { p->key = new_interned_string(p->key); } @@ -630,7 +630,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } ZEND_HASH_FOREACH_END(); /* class table hash keys, class names, properties, methods, constants, etc */ - ZEND_HASH_FOREACH_BUCKET(CG(class_table), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(CG(class_table), p) { zend_class_entry *ce; ce = (zend_class_entry*)Z_PTR(p->val); @@ -644,7 +644,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int ZEND_ASSERT(ZSTR_HAS_CE_CACHE(ce->name)); } - ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, q) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->properties_info, q) { zend_property_info *info; info = (zend_property_info*)Z_PTR(q->val); @@ -658,7 +658,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(&ce->function_table, q) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->function_table, q) { if (q->key) { q->key = new_interned_string(q->key); } @@ -667,7 +667,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, q) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, q) { if (q->key) { q->key = new_interned_string(q->key); } @@ -675,7 +675,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } ZEND_HASH_FOREACH_END(); /* constant hash keys */ - ZEND_HASH_FOREACH_BUCKET(EG(zend_constants), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(EG(zend_constants), p) { zend_constant *c; if (p->key) { @@ -691,7 +691,7 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } ZEND_HASH_FOREACH_END(); /* auto globals hash keys and names */ - ZEND_HASH_FOREACH_BUCKET(CG(auto_globals), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(CG(auto_globals), p) { zend_auto_global *auto_global; auto_global = (zend_auto_global*)Z_PTR(p->val); @@ -703,13 +703,13 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(&module_registry, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&module_registry, p) { if (p->key) { p->key = new_interned_string(p->key); } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(EG(ini_directives), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(EG(ini_directives), p) { zend_ini_entry *entry = (zend_ini_entry*)Z_PTR(p->val); if (p->key) { @@ -727,21 +727,21 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } ZEND_HASH_FOREACH_END(); ht = php_get_stream_filters_hash_global(); - ZEND_HASH_FOREACH_BUCKET(ht, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) { if (p->key) { p->key = new_interned_string(p->key); } } ZEND_HASH_FOREACH_END(); ht = php_stream_get_url_stream_wrappers_hash_global(); - ZEND_HASH_FOREACH_BUCKET(ht, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) { if (p->key) { p->key = new_interned_string(p->key); } } ZEND_HASH_FOREACH_END(); ht = php_stream_xport_get_hash(); - ZEND_HASH_FOREACH_BUCKET(ht, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) { if (p->key) { p->key = new_interned_string(p->key); } @@ -2405,7 +2405,7 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, i = 0; entry->dependencies_count = zend_hash_num_elements(dependencies); entry->dependencies = (zend_class_dependency*)ZCG(mem); - ZEND_HASH_FOREACH_STR_KEY_PTR(dependencies, dep_name, dep_ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(dependencies, dep_name, dep_ce) { #if ZEND_DEBUG ZEND_ASSERT(zend_accel_in_shm(dep_name)); #endif @@ -2588,7 +2588,7 @@ static void accel_reset_pcre_cache(void) return; } - ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) { /* Remove PCRE cache entries with inconsistent keys */ if (zend_accel_in_shm(p->key)) { p->key = NULL; @@ -3462,31 +3462,31 @@ static void preload_shutdown(void) #if 0 if (EG(zend_constants)) { - ZEND_HASH_REVERSE_FOREACH_VAL(EG(zend_constants), zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(zend_constants), zv) { zend_constant *c = Z_PTR_P(zv); if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) { break; } - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); } #endif if (EG(function_table)) { - ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(function_table), zv) { zend_function *func = Z_PTR_P(zv); if (func->type == ZEND_INTERNAL_FUNCTION) { break; } - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); } if (EG(class_table)) { - ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) { zend_class_entry *ce = Z_PTR_P(zv); if (ce->type == ZEND_INTERNAL_CLASS) { break; } - } ZEND_HASH_FOREACH_END_DEL(); + } ZEND_HASH_MAP_FOREACH_END_DEL(); } } @@ -3530,7 +3530,7 @@ static void preload_move_user_functions(HashTable *src, HashTable *dst) src->pDestructor = NULL; zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0); - ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) { + ZEND_HASH_MAP_REVERSE_FOREACH_BUCKET(src, p) { zend_function *function = Z_PTR(p->val); if (EXPECTED(function->type == ZEND_USER_FUNCTION)) { @@ -3569,7 +3569,7 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst) src->pDestructor = NULL; zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0); - ZEND_HASH_FOREACH_BUCKET_FROM(src, p, EG(persistent_classes_count)) { + ZEND_HASH_MAP_FOREACH_BUCKET_FROM(src, p, EG(persistent_classes_count)) { zend_class_entry *ce = Z_PTR(p->val); ZEND_ASSERT(ce->type == ZEND_USER_CLASS); if (ce->info.user.filename != filename) { @@ -3734,7 +3734,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) do { ok = 1; changed = 0; - ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { val = &c->value; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { if (EXPECTED(preload_update_constant(val, c->ce) == SUCCESS)) { @@ -3875,7 +3875,7 @@ static void preload_link(void) do { changed = 0; - ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(EG(class_table), key, zv, EG(persistent_classes_count)) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL_FROM(EG(class_table), key, zv, EG(persistent_classes_count)) { ce = Z_PTR_P(zv); ZEND_ASSERT(ce->type != ZEND_INTERNAL_CLASS); @@ -3966,7 +3966,7 @@ static void preload_link(void) do { changed = 0; - ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { + ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) { ce = Z_PTR_P(zv); if (ce->type == ZEND_INTERNAL_CLASS) { break; @@ -3984,7 +3984,7 @@ static void preload_link(void) } while (changed); /* Warn for classes that could not be linked. */ - ZEND_HASH_FOREACH_STR_KEY_VAL_FROM( + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL_FROM( EG(class_table), key, zv, EG(persistent_classes_count)) { ce = Z_PTR_P(zv); ZEND_ASSERT(ce->type != ZEND_INTERNAL_CLASS); @@ -4015,7 +4015,7 @@ static void preload_link(void) zend_hash_destroy(&errors); - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { zend_op_array *op_array = &script->script.main_op_array; preload_remove_declares(op_array); @@ -4030,12 +4030,12 @@ static void preload_link(void) /* Dynamic defs inside functions and methods need to be removed as well. */ zend_op_array *op_array; - ZEND_HASH_FOREACH_PTR_FROM(EG(function_table), op_array, EG(persistent_functions_count)) { + ZEND_HASH_MAP_FOREACH_PTR_FROM(EG(function_table), op_array, EG(persistent_functions_count)) { ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION); preload_remove_declares(op_array); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR_FROM(EG(class_table), ce, EG(persistent_classes_count)) { - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR_FROM(EG(class_table), ce, EG(persistent_classes_count)) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->type == ZEND_USER_FUNCTION) { preload_remove_declares(op_array); } @@ -4057,14 +4057,14 @@ static void preload_remove_empty_includes(void) bool changed; /* mark all as empty */ - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { script->empty = 1; } ZEND_HASH_FOREACH_END(); /* find non empty scripts */ do { changed = 0; - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { if (script->empty) { int empty = 1; zend_op *opline = script->script.main_op_array.opcodes; @@ -4106,7 +4106,7 @@ static void preload_remove_empty_includes(void) } while (changed); /* remove empty includes */ - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { zend_op *opline = script->script.main_op_array.opcodes; zend_op *end = opline + script->script.main_op_array.last; @@ -4139,7 +4139,7 @@ static void preload_remove_empty_includes(void) static void preload_register_trait_methods(zend_class_entry *ce) { zend_op_array *op_array; - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { ZEND_ASSERT(op_array->refcount && "Must have refcount pointer"); zend_shared_alloc_register_xlat_entry(op_array->refcount, op_array); @@ -4151,7 +4151,7 @@ static void preload_fix_trait_methods(zend_class_entry *ce) { zend_op_array *op_array; - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE) { zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->refcount); ZEND_ASSERT(orig_op_array && "Must be in xlat table"); @@ -4178,14 +4178,14 @@ static void preload_optimize(zend_persistent_script *script) zend_shared_alloc_init_xlat_table(); - ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { if (ce->ce_flags & ZEND_ACC_TRAIT) { preload_register_trait_methods(ce); } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR(preload_scripts, tmp_script) { - ZEND_HASH_FOREACH_PTR(&tmp_script->script.class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, tmp_script) { + ZEND_HASH_MAP_FOREACH_PTR(&tmp_script->script.class_table, ce) { if (ce->ce_flags & ZEND_ACC_TRAIT) { preload_register_trait_methods(ce); } @@ -4195,19 +4195,19 @@ static void preload_optimize(zend_persistent_script *script) zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level); zend_accel_finalize_delayed_early_binding_list(script); - ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { preload_fix_trait_methods(ce); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { - ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { preload_fix_trait_methods(ce); } ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END(); zend_shared_alloc_destroy_xlat_table(); - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level); zend_accel_finalize_delayed_early_binding_list(script); } ZEND_HASH_FOREACH_END(); @@ -4442,7 +4442,7 @@ static int accel_preload(const char *config, bool in_child) if (EG(zend_constants)) { /* Remember __COMPILER_HALT_OFFSET__(s). Do this early, * as zend_shutdown_executor_values() destroys constants. */ - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { zend_execute_data *orig_execute_data = EG(current_execute_data); zend_execute_data fake_execute_data; zval *offset; @@ -4547,7 +4547,7 @@ static int accel_preload(const char *config, bool in_child) i = 0; ZCSG(saved_scripts) = zend_shared_alloc((zend_hash_num_elements(preload_scripts) + 1) * sizeof(void*)); - ZEND_HASH_FOREACH_PTR(preload_scripts, script) { + ZEND_HASH_MAP_FOREACH_PTR(preload_scripts, script) { if (zend_hash_num_elements(&script->script.class_table) > 1) { zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0); } diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index dc2e3a33fedf1..720680a8f19d6 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4266,7 +4266,7 @@ void zend_jit_check_funcs(HashTable *function_table, bool is_method) { uintptr_t counter; zend_jit_op_array_extension *jit_extension; - ZEND_HASH_REVERSE_FOREACH_PTR(function_table, func) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(function_table, func) { if (func->type == ZEND_INTERNAL_FUNCTION) { break; } @@ -4570,8 +4570,8 @@ ZEND_EXT_API int zend_jit_script(zend_script *script) zend_class_entry *ce; zend_op_array *op_array; - ZEND_HASH_FOREACH_PTR(&script->class_table, ce) { - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&script->class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (!ZEND_FUNC_INFO(op_array)) { void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes); @@ -5053,7 +5053,7 @@ ZEND_EXT_API void zend_jit_deactivate(void) zend_jit_unprotect(); zend_jit_check_funcs(EG(function_table), 0); - ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) { + ZEND_HASH_MAP_REVERSE_FOREACH_PTR(EG(class_table), ce) { if (ce->type == ZEND_INTERNAL_CLASS) { break; } @@ -5108,12 +5108,12 @@ static void zend_jit_restart_preloaded_script(zend_persistent_script *script) zend_jit_restart_preloaded_op_array(&script->script.main_op_array); - ZEND_HASH_FOREACH_PTR(&script->script.function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&script->script.function_table, op_array) { zend_jit_restart_preloaded_op_array(op_array); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) { - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->type == ZEND_USER_FUNCTION) { zend_jit_restart_preloaded_op_array(op_array); } diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 21d8392b6cb6e..16f1781a0b799 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -5083,15 +5083,15 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o } else { | bls >2 // NOT_FOUND } - | // _ret = &_ht->arData[_h].val; + | // _ret = &_ht->arPacked[_h].val; if (val >= 0) { - | ldr REG0, [FCARG1x, #offsetof(zend_array, arData)] + | ldr REG0, [FCARG1x, #offsetof(zend_array, arPacked)] if (val != 0) { - | ADD_SUB_64_WITH_CONST add, REG0, REG0, (val * sizeof(Bucket)), TMP1 + | ADD_SUB_64_WITH_CONST add, REG0, REG0, (val * sizeof(zval)), TMP1 } } else { - | ldr TMP1, [FCARG1x, #offsetof(zend_array, arData)] - | add REG0, TMP1, FCARG2x, lsl #5 + | ldr TMP1, [FCARG1x, #offsetof(zend_array, arPacked)] + | add REG0, TMP1, FCARG2x, lsl #4 } } } @@ -13805,7 +13805,11 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend | LOAD_ADDR FCARG1x, jumptable | ldr TMP1, [FCARG1x, #offsetof(HashTable, arData)] | sub REG0, REG0, TMP1 - | mov FCARG1x, #(sizeof(Bucket) / sizeof(void*)) + if (HT_IS_PACKED(jumptable)) { + | mov FCARG1x, #(sizeof(zval) / sizeof(void*)) + } else { + | mov FCARG1x, #(sizeof(Bucket) / sizeof(void*)) + } | sdiv REG0, REG0, FCARG1x | adr FCARG1x, >4 | ldr TMP1, [FCARG1x, REG0] @@ -13842,7 +13846,11 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend | .addr &exit_addr } } - p++; + if (HT_IS_PACKED(jumptable)) { + p = (Bucket*)(((zval*)p)+1); + } else { + p++; + } count--; } while (count); |.code @@ -13961,7 +13969,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o } if (HT_IS_PACKED(jumptable)) { uint32_t count = jumptable->nNumUsed; - Bucket *p = jumptable->arData; + zval *zv = jumptable->arPacked; | CMP_64_WITH_CONST_32 FCARG2x, jumptable->nNumUsed, TMP1 if (default_label) { @@ -13981,9 +13989,8 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o if (trace_info) { trace_info->jmp_table_size += count; } - p = jumptable->arData; do { - if (Z_TYPE(p->val) == IS_UNDEF) { + if (Z_TYPE_P(zv) == IS_UNDEF) { if (default_label) { | .addr &default_label } else if (next_opline) { @@ -13992,7 +13999,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | .addr =>default_b } } else { - target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL(p->val)); + target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(zv)); if (!next_opline) { b = ssa->cfg.map[target - op_array->opcodes]; | .addr =>b @@ -14004,7 +14011,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | .addr &exit_addr } } - p++; + zv++; count--; } while (count); |.code @@ -14310,84 +14317,166 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o | // array = EX_VAR(opline->op1.var); | // fe_ht = Z_ARRVAL_P(array); | GET_ZVAL_PTR FCARG1x, op1_addr, TMP1 + + if (op1_info & MAY_BE_PACKED_GUARD) { + int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_PACKED_GUARD); + const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + + if (!exit_addr) { + return 0; + } + if (op1_info & MAY_BE_ARRAY_PACKED) { + | ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)] + | TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w + | beq &exit_addr + } else { + | ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)] + | TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w + | bne &exit_addr + } + } + | // pos = Z_FE_POS_P(array); | MEM_ACCESS_32_WITH_UOFFSET ldr, REG0w, FP, (opline->op1.var + offsetof(zval, u2.fe_pos)), TMP1 - | // p = fe_ht->arData + pos; - || ZEND_ASSERT(sizeof(Bucket) == 32); - | mov FCARG2w, REG0w - | ldr TMP1, [FCARG1x, #offsetof(zend_array, arData)] - | add FCARG2x, TMP1, FCARG2x, lsl #5 - |1: - | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - | ldr TMP1w, [FCARG1x, #offsetof(zend_array, nNumUsed)] - | cmp TMP1w, REG0w - | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - | // ZEND_VM_CONTINUE(); - if (exit_addr) { - if (exit_opcode == ZEND_JMP) { - | bls &exit_addr + + if (MAY_BE_HASH(op1_info)) { + if (MAY_BE_PACKED(op1_info)) { + | ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)] + | TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w + | bne >2 + } + | // p = fe_ht->arData + pos; + || ZEND_ASSERT(sizeof(Bucket) == 32); + | mov FCARG2w, REG0w + | ldr TMP1, [FCARG1x, #offsetof(zend_array, arData)] + | add FCARG2x, TMP1, FCARG2x, lsl #5 + |1: + | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + | ldr TMP1w, [FCARG1x, #offsetof(zend_array, nNumUsed)] + | cmp TMP1w, REG0w + | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + | // ZEND_VM_CONTINUE(); + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | bls &exit_addr + } else { + | bls >3 + } } else { - | bls >3 + | bls =>target_label + } + | // pos++; + | add REG0w, REG0w, #1 + | // value_type = Z_TYPE_INFO_P(value); + | // if (EXPECTED(value_type != IS_UNDEF)) { + if (!exit_addr || exit_opcode == ZEND_JMP) { + | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, >3, TMP1w + } else { + | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, &exit_addr, TMP1w + } + | // p++; + | add FCARG2x, FCARG2x, #sizeof(Bucket) + | b <1 + if (MAY_BE_PACKED(op1_info)) { + |2: } - } else { - | bls =>target_label } - | // pos++; - | add REG0w, REG0w, #1 - | // value_type = Z_TYPE_INFO_P(value); - | // if (EXPECTED(value_type != IS_UNDEF)) { - if (!exit_addr || exit_opcode == ZEND_JMP) { - | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, >3, TMP1w - } else { - | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, &exit_addr, TMP1w + if (MAY_BE_PACKED(op1_info)) { + | // p = fe_ht->arPacked + pos; + || ZEND_ASSERT(sizeof(zval) == 16); + | mov FCARG2w, REG0w + | ldr TMP1, [FCARG1x, #offsetof(zend_array, arPacked)] + | add FCARG2x, TMP1, FCARG2x, lsl #4 + |1: + | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + | ldr TMP1w, [FCARG1x, #offsetof(zend_array, nNumUsed)] + | cmp TMP1w, REG0w + | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + | // ZEND_VM_CONTINUE(); + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | bls &exit_addr + } else { + | bls >4 + } + } else { + | bls =>target_label + } + | // pos++; + | add REG0w, REG0w, #1 + | // value_type = Z_TYPE_INFO_P(value); + | // if (EXPECTED(value_type != IS_UNDEF)) { + if (!exit_addr || exit_opcode == ZEND_JMP) { + | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, >4, TMP1w + } else { + | IF_NOT_Z_TYPE FCARG2x, IS_UNDEF, &exit_addr, TMP1w + } + | // p++; + | add FCARG2x, FCARG2x, #sizeof(zval) + | b <1 } - | // p++; - | add FCARG2x, FCARG2x, #sizeof(Bucket) - | b <1 - |3: if (!exit_addr || exit_opcode == ZEND_JMP) { zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG2, 0); zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var); uint32_t val_info; - | // Z_FE_POS_P(array) = pos + 1; - | MEM_ACCESS_32_WITH_UOFFSET str, REG0w, FP, (opline->op1.var + offsetof(zval, u2.fe_pos)), TMP1 - if (RETURN_VALUE_USED(opline)) { zend_jit_addr res_addr = RES_ADDR(); - if ((op1_info & MAY_BE_ARRAY_KEY_LONG) - && (op1_info & MAY_BE_ARRAY_KEY_STRING)) { - | // if (!p->key) { - | ldr REG0, [FCARG2x, #offsetof(Bucket, key)] - | cbz REG0, >2 - } - if (op1_info & MAY_BE_ARRAY_KEY_STRING) { - | // ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); - | ldr REG0, [FCARG2x, #offsetof(Bucket, key)] - | SET_ZVAL_PTR res_addr, REG0, TMP1 - | ldr TMP1w, [REG0, #offsetof(zend_refcounted, gc.u.type_info)] - | TST_32_WITH_CONST TMP1w, IS_STR_INTERNED, TMP2w - | beq >1 - | SET_ZVAL_TYPE_INFO res_addr, IS_STRING, TMP1w, TMP2 - | b >3 - |1: - | GC_ADDREF REG0, TMP1w - | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX, TMP1w, TMP2 + if (MAY_BE_HASH(op1_info)) { + |3: + | // Z_FE_POS_P(array) = pos + 1; + | MEM_ACCESS_32_WITH_UOFFSET str, REG0w, FP, (opline->op1.var + offsetof(zval, u2.fe_pos)), TMP1 + + if ((op1_info & MAY_BE_ARRAY_KEY_LONG) + && (op1_info & MAY_BE_ARRAY_KEY_STRING)) { + | // if (!p->key) { + | ldr REG0, [FCARG2x, #offsetof(Bucket, key)] + | cbz REG0, >2 + } + if (op1_info & MAY_BE_ARRAY_KEY_STRING) { + | // ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + | ldr REG0, [FCARG2x, #offsetof(Bucket, key)] + | SET_ZVAL_PTR res_addr, REG0, TMP1 + | ldr TMP1w, [REG0, #offsetof(zend_refcounted, gc.u.type_info)] + | TST_32_WITH_CONST TMP1w, IS_STR_INTERNED, TMP2w + | beq >1 + | SET_ZVAL_TYPE_INFO res_addr, IS_STRING, TMP1w, TMP2 + | b >3 + |1: + | GC_ADDREF REG0, TMP1w + | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX, TMP1w, TMP2 + if ((op1_info & MAY_BE_ARRAY_KEY_LONG) || MAY_BE_PACKED(op1_info)) { + | b >3 + |2: + } + } if (op1_info & MAY_BE_ARRAY_KEY_LONG) { - | b >3 - |2: + | // ZVAL_LONG(EX_VAR(opline->result.var), p->h); + | ldr REG0, [FCARG2x, #offsetof(Bucket, h)] + | SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1 + | SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2 + if (MAY_BE_PACKED(op1_info)) { + | b >3 + } } } - if (op1_info & MAY_BE_ARRAY_KEY_LONG) { - | // ZVAL_LONG(EX_VAR(opline->result.var), p->h); - | ldr REG0, [FCARG2x, #offsetof(Bucket, h)] + if (MAY_BE_PACKED(op1_info)) { + |4: + | // Z_FE_POS_P(array) = pos + 1; + | MEM_ACCESS_32_WITH_UOFFSET str, REG0w, FP, (opline->op1.var + offsetof(zval, u2.fe_pos)), TMP1 + | sub REG0w, REG0w, #1 | SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1 | SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2 } |3: + } else { + |3: + |4: + | // Z_FE_POS_P(array) = pos + 1; + | MEM_ACCESS_32_WITH_UOFFSET str, REG0w, FP, (opline->op1.var + offsetof(zval, u2.fe_pos)), TMP1 } val_info = ((op1_info & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT); @@ -14411,6 +14500,9 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o | ZVAL_COPY_VALUE var_addr, -1, val_addr, val_info, ZREG_REG0, ZREG_FCARG1, ZREG_TMP1, ZREG_TMP2, ZREG_FPR0 | TRY_ADDREF val_info, REG0w, FCARG1x, TMP1w } + } else { + |3: + |4: } return 1; diff --git a/ext/opcache/jit/zend_jit_disasm.c b/ext/opcache/jit/zend_jit_disasm.c index 621bf1991b8ea..afa0da5dc3af3 100644 --- a/ext/opcache/jit/zend_jit_disasm.c +++ b/ext/opcache/jit/zend_jit_disasm.c @@ -415,7 +415,7 @@ static int zend_jit_disasm(const char *name, /* label numbering */ n = 0; m = 0; - ZEND_HASH_FOREACH_VAL(&labels, z) { + ZEND_HASH_MAP_FOREACH_VAL(&labels, z) { if (Z_TYPE_P(z) == IS_FALSE) { m--; ZVAL_LONG(z, m); diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 35c702300adb5..3afde0206483a 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -1726,8 +1726,23 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin case ZEND_COUNT: case ZEND_QM_ASSIGN: case ZEND_FE_RESET_R: + ADD_OP1_TRACE_GUARD(); + break; case ZEND_FE_FETCH_R: ADD_OP1_TRACE_GUARD(); + if (op1_type == IS_ARRAY && (orig_op1_type & ~IS_TRACE_PACKED) == IS_ARRAY) { + + zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use]; + + if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) { + info->type |= MAY_BE_PACKED_GUARD; + if (orig_op1_type & IS_TRACE_PACKED) { + info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH); + } else { + info->type &= ~MAY_BE_ARRAY_PACKED; + } + } + } break; case ZEND_VERIFY_RETURN_TYPE: if (opline->op1_type == IS_UNUSED) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 07ca85a8c1a7f..214105f92c3fc 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -5557,20 +5557,20 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o } else { | jbe >2 // NOT_FOUND } - | // _ret = &_ht->arData[_h].val; + | // _ret = &_ht->arPacked[h]; if (val >= 0) { - | mov r0, aword [FCARG1a + offsetof(zend_array, arData)] + | mov r0, aword [FCARG1a + offsetof(zend_array, arPacked)] if (val != 0) { - | add r0, val * sizeof(Bucket) + | add r0, val * sizeof(zval) } } else { |.if X64 | mov r0, FCARG2a - | shl r0, 5 + | shl r0, 4 |.else - | imul r0, FCARG2a, sizeof(Bucket) + | imul r0, FCARG2a, sizeof(zval) |.endif - | add r0, aword [FCARG1a + offsetof(zend_array, arData)] + | add r0, aword [FCARG1a + offsetof(zend_array, arPacked)] } } } @@ -14650,7 +14650,11 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend } | LOAD_ADDR FCARG1a, jumptable | sub r0, aword [FCARG1a + offsetof(HashTable, arData)] - | mov FCARG1a, (sizeof(Bucket) / sizeof(void*)) + if (HT_IS_PACKED(jumptable)) { + | mov FCARG1a, (sizeof(zval) / sizeof(void*)) + } else { + | mov FCARG1a, (sizeof(Bucket) / sizeof(void*)) + } |.if X64 | cqo |.else @@ -14698,7 +14702,11 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend | .aword &exit_addr } } - p++; + if (HT_IS_PACKED(jumptable)) { + p = (Bucket*)(((zval*)p)+1); + } else { + p++; + } count--; } while (count); |.code @@ -14815,7 +14823,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o } if (HT_IS_PACKED(jumptable)) { uint32_t count = jumptable->nNumUsed; - Bucket *p = jumptable->arData; + zval *zv = jumptable->arPacked; | cmp FCARG2a, jumptable->nNumUsed if (default_label) { @@ -14841,9 +14849,8 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o if (trace_info) { trace_info->jmp_table_size += count; } - p = jumptable->arData; do { - if (Z_TYPE(p->val) == IS_UNDEF) { + if (Z_TYPE_P(zv) == IS_UNDEF) { if (default_label) { | .aword &default_label } else if (next_opline) { @@ -14852,7 +14859,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | .aword =>default_b } } else { - target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL(p->val)); + target = ZEND_OFFSET_TO_OPLINE(opline, Z_LVAL_P(zv)); if (!next_opline) { b = ssa->cfg.map[target - op_array->opcodes]; | .aword =>b @@ -14864,7 +14871,7 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o | .aword &exit_addr } } - p++; + zv++; count--; } while (count); |.code @@ -15175,86 +15182,166 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o | // array = EX_VAR(opline->op1.var); | // fe_ht = Z_ARRVAL_P(array); | GET_ZVAL_PTR FCARG1a, op1_addr + + if (op1_info & MAY_BE_PACKED_GUARD) { + int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_PACKED_GUARD); + const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + + if (!exit_addr) { + return 0; + } + if (op1_info & MAY_BE_ARRAY_PACKED) { + | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED + | jz &exit_addr + } else { + | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED + | jnz &exit_addr + } + } + | // pos = Z_FE_POS_P(array); | mov eax, dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)] - | // p = fe_ht->arData + pos; - |.if X64 - || ZEND_ASSERT(sizeof(Bucket) == 32); - | mov FCARG2d, eax - | shl FCARG2a, 5 - |.else - | imul FCARG2a, r0, sizeof(Bucket) - |.endif - | add FCARG2a, aword [FCARG1a + offsetof(zend_array, arData)] - |1: - | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { - | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], eax - | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - | // ZEND_VM_CONTINUE(); - if (exit_addr) { - if (exit_opcode == ZEND_JMP) { - | jbe &exit_addr + + if (MAY_BE_HASH(op1_info)) { + if (MAY_BE_PACKED(op1_info)) { + | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED + | jnz >2 + } + + | // p = fe_ht->arData + pos; + |.if X64 + || ZEND_ASSERT(sizeof(Bucket) == 32); + | mov FCARG2d, eax + | shl FCARG2a, 5 + |.else + | imul FCARG2a, r0, sizeof(Bucket) + |.endif + | add FCARG2a, aword [FCARG1a + offsetof(zend_array, arData)] + |1: + | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], eax + | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + | // ZEND_VM_CONTINUE(); + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | jbe &exit_addr + } else { + | jbe >3 + } } else { - | jbe >3 + | jbe =>target_label + } + | // pos++; + | add eax, 1 + | // value_type = Z_TYPE_INFO_P(value); + | // if (EXPECTED(value_type != IS_UNDEF)) { + if (!exit_addr || exit_opcode == ZEND_JMP) { + | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, >3 + } else { + | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, &exit_addr + } + | // p++; + | add FCARG2a, sizeof(Bucket) + | jmp <1 + if (MAY_BE_PACKED(op1_info)) { + |2: } - } else { - | jbe =>target_label } - | // pos++; - | add eax, 1 - | // value_type = Z_TYPE_INFO_P(value); - | // if (EXPECTED(value_type != IS_UNDEF)) { - if (!exit_addr || exit_opcode == ZEND_JMP) { - | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, >3 - } else { - | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, &exit_addr + if (MAY_BE_PACKED(op1_info)) { + | // p = fe_ht->arPacked + pos; + || ZEND_ASSERT(sizeof(zval) == 16); + | mov FCARG2d, eax + | shl FCARG2a, 4 + | add FCARG2a, aword [FCARG1a + offsetof(zend_array, arPacked)] + |1: + | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], eax + | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + | // ZEND_VM_CONTINUE(); + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | jbe &exit_addr + } else { + | jbe >4 + } + } else { + | jbe =>target_label + } + | // pos++; + | add eax, 1 + | // value_type = Z_TYPE_INFO_P(value); + | // if (EXPECTED(value_type != IS_UNDEF)) { + if (!exit_addr || exit_opcode == ZEND_JMP) { + | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, >4 + } else { + | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, &exit_addr + } + | // p++; + | add FCARG2a, sizeof(zval) + | jmp <1 } - | // p++; - | add FCARG2a, sizeof(Bucket) - | jmp <1 - |3: + if (!exit_addr || exit_opcode == ZEND_JMP) { zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG2, 0); zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var); uint32_t val_info; - | // Z_FE_POS_P(array) = pos + 1; - | mov dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)], eax - if (RETURN_VALUE_USED(opline)) { zend_jit_addr res_addr = RES_ADDR(); - if ((op1_info & MAY_BE_ARRAY_KEY_LONG) - && (op1_info & MAY_BE_ARRAY_KEY_STRING)) { - | // if (!p->key) { - | cmp aword [FCARG2a + offsetof(Bucket, key)], 0 - | jz >2 - } - if (op1_info & MAY_BE_ARRAY_KEY_STRING) { - | // ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); - | mov r0, aword [FCARG2a + offsetof(Bucket, key)] - | SET_ZVAL_PTR res_addr, r0 - | test dword [r0 + offsetof(zend_refcounted, gc.u.type_info)], IS_STR_INTERNED - | jz >1 - | SET_ZVAL_TYPE_INFO res_addr, IS_STRING - | jmp >3 - |1: - | GC_ADDREF r0 - | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX + if (MAY_BE_HASH(op1_info)) { + |3: + | // Z_FE_POS_P(array) = pos + 1; + | mov dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)], eax + + if ((op1_info & MAY_BE_ARRAY_KEY_LONG) + && (op1_info & MAY_BE_ARRAY_KEY_STRING)) { + | // if (!p->key) { + | cmp aword [FCARG2a + offsetof(Bucket, key)], 0 + | jz >2 + } + if (op1_info & MAY_BE_ARRAY_KEY_STRING) { + | // ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + | mov r0, aword [FCARG2a + offsetof(Bucket, key)] + | SET_ZVAL_PTR res_addr, r0 + | test dword [r0 + offsetof(zend_refcounted, gc.u.type_info)], IS_STR_INTERNED + | jz >1 + | SET_ZVAL_TYPE_INFO res_addr, IS_STRING + | jmp >3 + |1: + | GC_ADDREF r0 + | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX + if ((op1_info & MAY_BE_ARRAY_KEY_LONG) || MAY_BE_PACKED(op1_info)) { + | jmp >3 + |2: + } + } if (op1_info & MAY_BE_ARRAY_KEY_LONG) { - | jmp >3 - |2: + | // ZVAL_LONG(EX_VAR(opline->result.var), p->h); + | mov r0, aword [FCARG2a + offsetof(Bucket, h)] + | SET_ZVAL_LVAL res_addr, r0 + | SET_ZVAL_TYPE_INFO res_addr, IS_LONG + if (MAY_BE_PACKED(op1_info)) { + | jmp >3 + } } } - if (op1_info & MAY_BE_ARRAY_KEY_LONG) { - | // ZVAL_LONG(EX_VAR(opline->result.var), p->h); - | mov r0, aword [FCARG2a + offsetof(Bucket, h)] + if (MAY_BE_PACKED(op1_info)) { + |4: + | // Z_FE_POS_P(array) = pos + 1; + | mov dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)], eax + | sub r0, 1 | SET_ZVAL_LVAL res_addr, r0 | SET_ZVAL_TYPE_INFO res_addr, IS_LONG } |3: + } else { + |3: + |4: + | // Z_FE_POS_P(array) = pos + 1; + | mov dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)], eax } val_info = ((op1_info & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT); @@ -15278,6 +15365,9 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o | ZVAL_COPY_VALUE var_addr, -1, val_addr, val_info, ZREG_R0, ZREG_FCARG1 | TRY_ADDREF val_info, ah, FCARG1a } + } else { + |3: + |4: } return 1; diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index da1696bb92083..f785303c936a7 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -649,7 +649,7 @@ ZEND_FUNCTION(opcache_get_status) zend_op_array *op_array; array_init(&scripts); - ZEND_HASH_FOREACH_PTR(&ZCSG(preload_script)->script.function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ZCSG(preload_script)->script.function_table, op_array) { add_next_index_str(&scripts, op_array->function_name); } ZEND_HASH_FOREACH_END(); add_assoc_zval(&statistics, "functions", &scripts); @@ -660,7 +660,7 @@ ZEND_FUNCTION(opcache_get_status) zend_string *key; array_init(&scripts); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ZCSG(preload_script)->script.class_table, key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ZCSG(preload_script)->script.class_table, key, ce) { if (ce->refcount > 1 && !zend_string_equals_ci(key, ce->name)) { add_next_index_str(&scripts, key); } else { diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index b34f434d7c672..578556b8ef395 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -299,8 +299,6 @@ static void zend_file_cache_serialize_hash(HashTable *ht, void *buf, serialize_callback_t func) { - Bucket *p, *end; - if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) { ht->arData = NULL; return; @@ -308,16 +306,33 @@ static void zend_file_cache_serialize_hash(HashTable *ht, if (IS_SERIALIZED(ht->arData)) { return; } - SERIALIZE_PTR(ht->arData); - p = ht->arData; - UNSERIALIZE_PTR(p); - end = p + ht->nNumUsed; - while (p < end) { - if (Z_TYPE(p->val) != IS_UNDEF) { - SERIALIZE_STR(p->key); - func(&p->val, script, info, buf); + if (HT_IS_PACKED(ht)) { + zval *p, *end; + + SERIALIZE_PTR(ht->arPacked); + p = ht->arPacked; + UNSERIALIZE_PTR(p); + end = p + ht->nNumUsed; + while (p < end) { + if (Z_TYPE_P(p) != IS_UNDEF) { + func(p, script, info, buf); + } + p++; + } + } else { + Bucket *p, *end; + + SERIALIZE_PTR(ht->arData); + p = ht->arData; + UNSERIALIZE_PTR(p); + end = p + ht->nNumUsed; + while (p < end) { + if (Z_TYPE(p->val) != IS_UNDEF) { + SERIALIZE_STR(p->key); + func(&p->val, script, info, buf); + } + p++; } - p++; } } @@ -1107,8 +1122,6 @@ static void zend_file_cache_unserialize_hash(HashTable *ht, unserialize_callback_t func, dtor_func_t dtor) { - Bucket *p, *end; - ht->pDestructor = dtor; if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) { if (EXPECTED(!file_cache_only)) { @@ -1122,14 +1135,29 @@ static void zend_file_cache_unserialize_hash(HashTable *ht, return; } UNSERIALIZE_PTR(ht->arData); - p = ht->arData; - end = p + ht->nNumUsed; - while (p < end) { - if (Z_TYPE(p->val) != IS_UNDEF) { - UNSERIALIZE_STR(p->key); - func(&p->val, script, buf); + if (HT_IS_PACKED(ht)) { + zval *p, *end; + + p = ht->arPacked; + end = p + ht->nNumUsed; + while (p < end) { + if (Z_TYPE_P(p) != IS_UNDEF) { + func(p, script, buf); + } + p++; + } + } else { + Bucket *p, *end; + + p = ht->arData; + end = p + ht->nNumUsed; + while (p < end) { + if (Z_TYPE(p->val) != IS_UNDEF) { + UNSERIALIZE_STR(p->key); + func(&p->val, script, buf); + } + p++; } - p++; } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 4a8c3fa47bc6e..0523f052ebd13 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -115,12 +115,12 @@ static void zend_hash_persist(HashTable *ht) HT_FLAGS(ht) |= HASH_FLAG_UNINITIALIZED; return; } - if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(ht)) { void *data = HT_GET_DATA_ADDR(ht); if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) { - data = zend_shared_memdup(data, HT_USED_SIZE(ht)); + data = zend_shared_memdup(data, HT_PACKED_USED_SIZE(ht)); } else { - data = zend_shared_memdup_free(data, HT_USED_SIZE(ht)); + data = zend_shared_memdup_free(data, HT_PACKED_USED_SIZE(ht)); } HT_SET_DATA_ADDR(ht, data); } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { @@ -215,21 +215,32 @@ static void zend_persist_zval(zval *z) && zend_accel_in_shm(Z_ARR_P(z))) { /* pass */ } else { - Bucket *p; + HashTable *ht; if (!Z_REFCOUNTED_P(z)) { - Z_ARR_P(z) = zend_shared_memdup_put(Z_ARR_P(z), sizeof(zend_array)); + ht = zend_shared_memdup_put(Z_ARR_P(z), sizeof(zend_array)); } else { GC_REMOVE_FROM_BUFFER(Z_ARR_P(z)); - Z_ARR_P(z) = zend_shared_memdup_put_free(Z_ARR_P(z), sizeof(zend_array)); + ht = zend_shared_memdup_put_free(Z_ARR_P(z), sizeof(zend_array)); + } + Z_ARR_P(z) = ht; + zend_hash_persist(ht); + if (HT_IS_PACKED(ht)) { + zval *zv; + + ZEND_HASH_PACKED_FOREACH_VAL(ht, zv) { + zend_persist_zval(zv); + } ZEND_HASH_FOREACH_END(); + } else { + Bucket *p; + + ZEND_HASH_MAP_FOREACH_BUCKET(ht, p) { + if (p->key) { + zend_accel_store_interned_string(p->key); + } + zend_persist_zval(&p->val); + } ZEND_HASH_FOREACH_END(); } - zend_hash_persist(Z_ARRVAL_P(z)); - ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { - if (p->key) { - zend_accel_store_interned_string(p->key); - } - zend_persist_zval(&p->val); - } ZEND_HASH_FOREACH_END(); /* make immutable array */ Z_TYPE_FLAGS_P(z) = 0; GC_SET_REFCOUNT(Z_COUNTED_P(z), 2); @@ -274,7 +285,7 @@ static HashTable *zend_persist_attributes(HashTable *attributes) zend_hash_persist(attributes); - ZEND_HASH_FOREACH_VAL(attributes, v) { + ZEND_HASH_PACKED_FOREACH_VAL(attributes, v) { zend_attribute *attr = Z_PTR_P(v); zend_attribute *copy = zend_shared_memdup_put_free(attr, ZEND_ATTRIBUTE_SIZE(attr->argc)); @@ -328,15 +339,24 @@ uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name) static HashTable *zend_persist_backed_enum_table(HashTable *backed_enum_table) { HashTable *ptr; - Bucket *p; zend_hash_persist(backed_enum_table); - ZEND_HASH_FOREACH_BUCKET(backed_enum_table, p) { - if (p->key != NULL) { - zend_accel_store_interned_string(p->key); - } - zend_persist_zval(&p->val); - } ZEND_HASH_FOREACH_END(); + if (HT_IS_PACKED(backed_enum_table)) { + zval *zv; + + ZEND_HASH_PACKED_FOREACH_VAL(backed_enum_table, zv) { + zend_persist_zval(zv); + } ZEND_HASH_FOREACH_END(); + } else { + Bucket *p; + + ZEND_HASH_MAP_FOREACH_BUCKET(backed_enum_table, p) { + if (p->key != NULL) { + zend_accel_store_interned_string(p->key); + } + zend_persist_zval(&p->val); + } ZEND_HASH_FOREACH_END(); + } ptr = zend_shared_memdup_free(backed_enum_table, sizeof(HashTable)); GC_SET_REFCOUNT(ptr, 2); @@ -493,7 +513,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc Bucket *p; zend_hash_persist(op_array->static_variables); - ZEND_HASH_FOREACH_BUCKET(op_array->static_variables, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(op_array->static_variables, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); zend_persist_zval(&p->val); @@ -882,7 +902,7 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) } zend_hash_persist(&ce->function_table); - ZEND_HASH_FOREACH_BUCKET(&ce->function_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->function_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); zend_persist_class_method(&p->val, ce); @@ -916,7 +936,7 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) } zend_hash_persist(&ce->constants_table); - ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); zend_persist_class_constant(&p->val); @@ -924,7 +944,7 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); zend_hash_persist(&ce->properties_info); - ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->properties_info, p) { zend_property_info *prop = Z_PTR(p->val); ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); @@ -1208,12 +1228,12 @@ static void zend_accel_persist_class_table(HashTable *class_table) JIT_G(on) = 0; #endif zend_hash_persist(class_table); - ZEND_HASH_FOREACH_BUCKET(class_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); Z_CE(p->val) = zend_persist_class_entry(Z_CE(p->val)); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(class_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { ce = Z_PTR(p->val); zend_update_parent_ce(ce); @@ -1225,10 +1245,10 @@ static void zend_accel_persist_class_table(HashTable *class_table) !ZCG(current_persistent_script)->corrupted) { zend_op_array *op_array; - ZEND_HASH_FOREACH_BUCKET(class_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { ce = Z_PTR(p->val); - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->type == ZEND_USER_FUNCTION) { if (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { @@ -1241,10 +1261,10 @@ static void zend_accel_persist_class_table(HashTable *class_table) } ZEND_HASH_FOREACH_END(); } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_BUCKET(class_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { ce = Z_PTR(p->val); - ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { if (op_array->type == ZEND_USER_FUNCTION) { if ((op_array->scope != ce || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) @@ -1328,7 +1348,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script zend_accel_persist_class_table(&script->script.class_table); zend_hash_persist(&script->script.function_table); - ZEND_HASH_FOREACH_BUCKET(&script->script.function_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&script->script.function_table, p) { ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); zend_persist_op_array(&p->val); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index ed9a75bfced7c..1eac4684c58af 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -54,7 +54,9 @@ static void zend_hash_persist_calc(HashTable *ht) return; } - if (!(HT_FLAGS(ht) & HASH_FLAG_PACKED) && ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { + if (HT_IS_PACKED(ht)) { + ADD_SIZE(HT_PACKED_USED_SIZE(ht)); + } else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) { /* compact table */ uint32_t hash_size; @@ -112,16 +114,26 @@ static void zend_persist_zval_calc(zval *z) } size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array)); if (size) { - Bucket *p; + HashTable *ht = Z_ARRVAL_P(z); ADD_SIZE(size); - zend_hash_persist_calc(Z_ARRVAL_P(z)); - ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { - if (p->key) { - ADD_INTERNED_STRING(p->key); - } - zend_persist_zval_calc(&p->val); - } ZEND_HASH_FOREACH_END(); + zend_hash_persist_calc(ht); + if (HT_IS_PACKED(ht)) { + zval *zv; + + ZEND_HASH_PACKED_FOREACH_VAL(Z_ARRVAL_P(z), zv) { + zend_persist_zval_calc(zv); + } ZEND_HASH_FOREACH_END(); + } else { + Bucket *p; + + ZEND_HASH_MAP_FOREACH_BUCKET(Z_ARRVAL_P(z), p) { + if (p->key) { + ADD_INTERNED_STRING(p->key); + } + zend_persist_zval_calc(&p->val); + } ZEND_HASH_FOREACH_END(); + } } break; case IS_CONSTANT_AST: @@ -152,7 +164,7 @@ static void zend_persist_attributes_calc(HashTable *attributes) ADD_SIZE(sizeof(HashTable)); zend_hash_persist_calc(attributes); - ZEND_HASH_FOREACH_PTR(attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) { ADD_SIZE(ZEND_ATTRIBUTE_SIZE(attr->argc)); ADD_INTERNED_STRING(attr->name); ADD_INTERNED_STRING(attr->lcname); @@ -216,7 +228,7 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) zend_shared_alloc_register_xlat_entry(op_array->static_variables, op_array->static_variables); ADD_SIZE(sizeof(HashTable)); zend_hash_persist_calc(op_array->static_variables); - ZEND_HASH_FOREACH_BUCKET(op_array->static_variables, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(op_array->static_variables, p) { ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); zend_persist_zval_calc(&p->val); @@ -407,7 +419,7 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } zend_hash_persist_calc(&ce->function_table); - ZEND_HASH_FOREACH_BUCKET(&ce->function_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->function_table, p) { ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); zend_persist_class_method_calc(&p->val); @@ -431,14 +443,14 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } } zend_hash_persist_calc(&ce->constants_table); - ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, p) { ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); zend_persist_class_constant_calc(&p->val); } ZEND_HASH_FOREACH_END(); zend_hash_persist_calc(&ce->properties_info); - ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&ce->properties_info, p) { zend_property_info *prop = Z_PTR(p->val); ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); @@ -534,15 +546,24 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) } if (ce->backed_enum_table) { - Bucket *p; ADD_SIZE(sizeof(HashTable)); zend_hash_persist_calc(ce->backed_enum_table); - ZEND_HASH_FOREACH_BUCKET(ce->backed_enum_table, p) { - if (p->key != NULL) { - ADD_INTERNED_STRING(p->key); - } - zend_persist_zval_calc(&p->val); - } ZEND_HASH_FOREACH_END(); + if (HT_IS_PACKED(ce->backed_enum_table)) { + zval *zv; + + ZEND_HASH_PACKED_FOREACH_VAL(ce->backed_enum_table, zv) { + zend_persist_zval_calc(zv); + } ZEND_HASH_FOREACH_END(); + } else { + Bucket *p; + + ZEND_HASH_MAP_FOREACH_BUCKET(ce->backed_enum_table, p) { + if (p->key != NULL) { + ADD_INTERNED_STRING(p->key); + } + zend_persist_zval_calc(&p->val); + } ZEND_HASH_FOREACH_END(); + } } } } @@ -552,7 +573,7 @@ static void zend_accel_persist_class_table_calc(HashTable *class_table) Bucket *p; zend_hash_persist_calc(class_table); - ZEND_HASH_FOREACH_BUCKET(class_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); zend_persist_class_entry_calc(Z_CE(p->val)); @@ -610,7 +631,7 @@ uint32_t zend_accel_script_persist_calc(zend_persistent_script *new_persistent_s zend_hash_rehash(&new_persistent_script->script.function_table); } zend_hash_persist_calc(&new_persistent_script->script.function_table); - ZEND_HASH_FOREACH_BUCKET(&new_persistent_script->script.function_table, p) { + ZEND_HASH_MAP_FOREACH_BUCKET(&new_persistent_script->script.function_table, p) { ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); zend_persist_op_array_calc(&p->val); diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index c7abfda2856d6..cb2a44c1cf57a 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -2115,7 +2115,7 @@ static zend_string *php_pcre_replace_array(HashTable *regex, tmp_replace_entry_str = NULL; break; } - zv = &replace_ht->arData[replace_idx].val; + zv = ZEND_HASH_ELEMENT(replace_ht, replace_idx); replace_idx++; if (Z_TYPE_P(zv) != IS_UNDEF) { replace_entry_str = zval_get_tmp_string(zv, &tmp_replace_entry_str); diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index b18efe462842a..f11b983a9a82f 100644 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -71,7 +71,7 @@ PHP_FUNCTION(pdo_drivers) array_init(return_value); - ZEND_HASH_FOREACH_PTR(&pdo_driver_hash, pdriver) { + ZEND_HASH_MAP_FOREACH_PTR(&pdo_driver_hash, pdriver) { add_next_index_stringl(return_value, pdriver->driver_name, pdriver->driver_name_len); } ZEND_HASH_FOREACH_END(); } @@ -277,7 +277,7 @@ PHP_MINFO_FUNCTION(pdo) php_info_print_table_start(); php_info_print_table_header(2, "PDO support", "enabled"); - ZEND_HASH_FOREACH_PTR(&pdo_driver_hash, pdriver) { + ZEND_HASH_MAP_FOREACH_PTR(&pdo_driver_hash, pdriver) { spprintf(&drivers, 0, "%s, %s", ldrivers, pdriver->driver_name); efree(ldrivers); ldrivers = drivers; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index d53d2ca63c0d1..479959db42bb0 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1187,7 +1187,7 @@ PHP_METHOD(PDO, getAvailableDrivers) array_init(return_value); - ZEND_HASH_FOREACH_PTR(&pdo_driver_hash, pdriver) { + ZEND_HASH_MAP_FOREACH_PTR(&pdo_driver_hash, pdriver) { add_next_index_stringl(return_value, (char*)pdriver->driver_name, pdriver->driver_name_len); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/phar/phar.c b/ext/phar/phar.c index bc08e4edde05d..91310c21e4967 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2015,7 +2015,7 @@ int phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const } else { zend_string *str_key; - ZEND_HASH_FOREACH_STR_KEY_PTR(&PHAR_G(phar_fname_map), str_key, pphar) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&PHAR_G(phar_fname_map), str_key, pphar) { if (ZSTR_LEN(str_key) > (uint32_t) filename_len) { continue; } @@ -2028,7 +2028,7 @@ int phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const } ZEND_HASH_FOREACH_END(); if (PHAR_G(manifest_cached)) { - ZEND_HASH_FOREACH_STR_KEY_PTR(&cached_phars, str_key, pphar) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&cached_phars, str_key, pphar) { if (ZSTR_LEN(str_key) > (uint32_t) filename_len) { continue; } @@ -2723,7 +2723,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv } new_manifest_count = 0; offset = 0; - ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&phar->manifest, entry) { if (entry->cfp) { /* did we forget to get rid of cfp last time? */ php_stream_close(entry->cfp); @@ -2955,7 +2955,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv manifest_ftell = php_stream_tell(newfile); /* now write the manifest */ - ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&phar->manifest, entry) { const zend_string *metadata_str; if (entry->is_deleted || entry->is_mounted) { /* remove this from the new phar if deleted, ignore if mounted */ @@ -3039,7 +3039,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv /* now copy the actual file data to the new phar */ offset = php_stream_tell(newfile); - ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&phar->manifest, entry) { if (entry->is_deleted || entry->is_dir || entry->is_mounted) { continue; } @@ -3251,7 +3251,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv if (shared_cfp != NULL) { php_stream_close(shared_cfp); } - ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&phar->manifest, entry) { if (entry->cfp) { entry->cfp = NULL; entry->header_offset = 0; @@ -3504,7 +3504,7 @@ void phar_request_initialize(void) /* {{{ */ phar_archive_data *pphar; phar_entry_fp *stuff = (phar_entry_fp *) ecalloc(zend_hash_num_elements(&cached_phars), sizeof(phar_entry_fp)); - ZEND_HASH_FOREACH_PTR(&cached_phars, pphar) { + ZEND_HASH_MAP_FOREACH_PTR(&cached_phars, pphar) { stuff[pphar->phar_pos].manifest = (phar_entry_fp_info *) ecalloc( zend_hash_num_elements(&(pphar->manifest)), sizeof(phar_entry_fp_info)); } ZEND_HASH_FOREACH_END(); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 448d03b7cc75e..a9bad08aa39f9 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -2250,7 +2250,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert phar_metadata_tracker_copy(&phar->metadata_tracker, &source->metadata_tracker, phar->is_persistent); /* first copy each file's uncompressed contents to a temporary file and set per-file flags */ - ZEND_HASH_FOREACH_PTR(&source->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&source->manifest, entry) { newentry = *entry; @@ -4269,13 +4269,13 @@ static int extract_helper(phar_archive_data *archive, zend_string *search, char if (!search) { /* nothing to match -- extract all files */ - ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; extracted++; } ZEND_HASH_FOREACH_END(); } else if ('/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) { /* ends in "/" -- extract all entries having that prefix */ - ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) { + ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { if (0 != strncmp(ZSTR_VAL(search), entry->filename, ZSTR_LEN(search))) continue; if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; extracted++; diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 745c3b429cf70..9bba67c6fc963 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -613,7 +613,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f if (HT_IS_INITIALIZED(&phar->mounted_dirs) && zend_hash_num_elements(&phar->mounted_dirs)) { zend_string *str_key; - ZEND_HASH_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) { if (ZSTR_LEN(str_key) >= internal_file_len || strncmp(ZSTR_VAL(str_key), internal_file, ZSTR_LEN(str_key))) { continue; } else { @@ -883,7 +883,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from uint32_t from_len = ZSTR_LEN(resource_from->path) - 1; uint32_t to_len = ZSTR_LEN(resource_to->path) - 1; - ZEND_HASH_FOREACH_BUCKET(&phar->manifest, b) { + ZEND_HASH_MAP_FOREACH_BUCKET(&phar->manifest, b) { str_key = b->key; entry = Z_PTR(b->val); if (!entry->is_deleted && @@ -910,7 +910,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from } ZEND_HASH_FOREACH_END(); zend_hash_rehash(&phar->manifest); - ZEND_HASH_FOREACH_BUCKET(&phar->virtual_dirs, b) { + ZEND_HASH_MAP_FOREACH_BUCKET(&phar->virtual_dirs, b) { str_key = b->key; if (ZSTR_LEN(str_key) >= from_len && memcmp(ZSTR_VAL(str_key), ZSTR_VAL(resource_from->path)+1, from_len) == 0 && @@ -928,7 +928,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from } ZEND_HASH_FOREACH_END(); zend_hash_rehash(&phar->virtual_dirs); - ZEND_HASH_FOREACH_BUCKET(&phar->mounted_dirs, b) { + ZEND_HASH_MAP_FOREACH_BUCKET(&phar->mounted_dirs, b) { str_key = b->key; if (ZSTR_LEN(str_key) >= from_len && memcmp(ZSTR_VAL(str_key), ZSTR_VAL(resource_from->path)+1, from_len) == 0 && diff --git a/ext/phar/util.c b/ext/phar/util.c index 515830bf2c70a..72e633a5b3324 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1290,7 +1290,7 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, si if (HT_IS_INITIALIZED(&phar->mounted_dirs) && zend_hash_num_elements(&phar->mounted_dirs)) { zend_string *str_key; - ZEND_HASH_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) { if (ZSTR_LEN(str_key) >= path_len || strncmp(ZSTR_VAL(str_key), path, ZSTR_LEN(str_key))) { continue; } else { @@ -2056,7 +2056,7 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */ *pphar = phar; /* now, scan the list of persistent Phar objects referencing this phar and update the pointers */ - ZEND_HASH_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) { + ZEND_HASH_MAP_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) { if (objphar->archive->fname_len == phar->fname_len && !memcmp(objphar->archive->fname, phar->fname, phar->fname_len)) { objphar->archive = phar; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 11024b9aee8cd..820520c0aedd1 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -384,7 +384,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char zend_string *key; zend_class_constant *c; - ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, c) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, c) { _class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent)); if (UNEXPECTED(EG(exception))) { zend_string_release(sub_indent); @@ -400,7 +400,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char if (count > 0) { zend_property_info *prop; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) { count_shadow_props++; } else if (prop->flags & ZEND_ACC_STATIC) { @@ -414,7 +414,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char if (count_static_props > 0) { zend_property_info *prop; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) { _property_string(str, prop, NULL, ZSTR_VAL(sub_indent)); } @@ -428,7 +428,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char if (count > 0) { zend_function *mptr; - ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_STATIC) && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce)) { @@ -442,7 +442,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char if (count_static_funcs > 0) { zend_function *mptr; - ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_STATIC) && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce)) { @@ -461,7 +461,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char if (count > 0) { zend_property_info *prop; - ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { if (!(prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) { _property_string(str, prop, NULL, ZSTR_VAL(sub_indent)); @@ -477,7 +477,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char count = 0; if (properties && zend_hash_num_elements(properties)) { - ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(properties, prop_name) { if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */ if (!zend_hash_exists(&ce->properties_info, prop_name)) { count++; @@ -500,7 +500,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char smart_str method_str = {0}; count = 0; - ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce)) { @@ -748,7 +748,7 @@ static void _function_closure_string(smart_str *str, zend_function *fptr, char* smart_str_append_printf(str, "\n"); smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables)); i = 0; - ZEND_HASH_FOREACH_STR_KEY(static_variables, key) { + ZEND_HASH_MAP_FOREACH_STR_KEY(static_variables, key) { smart_str_append_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key)); } ZEND_HASH_FOREACH_END(); smart_str_append_printf(str, "%s}\n", indent); @@ -1020,7 +1020,7 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i { smart_str str_ini = {0}; zend_ini_entry *ini_entry; - ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), ini_entry) { _extension_ini_string(ini_entry, &str_ini, indent, module->module_number); } ZEND_HASH_FOREACH_END(); if (smart_str_get_len(&str_ini) > 0) { @@ -1036,7 +1036,7 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i zend_constant *constant; int num_constants = 0; - ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) { + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) { if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) { _const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, indent); num_constants++; @@ -1055,7 +1055,7 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i zend_function *fptr; int first = 1; - ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) { + ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), fptr) { if (fptr->common.type==ZEND_INTERNAL_FUNCTION && fptr->internal_function.module == module) { if (first) { @@ -1077,7 +1077,7 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i zend_class_entry *ce; int num_classes = 0; - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { _extension_class_string(ce, key, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes); } ZEND_HASH_FOREACH_END(); if (num_classes) { @@ -1125,7 +1125,7 @@ static int read_attributes(zval *ret, HashTable *attributes, zend_class_entry *s // Name based filtering using lowercased key. zend_string *filter = zend_string_tolower(name); - ZEND_HASH_FOREACH_PTR(attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) { if (attr->offset == offset && zend_string_equals(attr->lcname, filter)) { reflection_attribute_factory(&tmp, attributes, attr, scope, target, filename); add_next_index_zval(ret, &tmp); @@ -1136,7 +1136,7 @@ static int read_attributes(zval *ret, HashTable *attributes, zend_class_entry *s return SUCCESS; } - ZEND_HASH_FOREACH_PTR(attributes, attr) { + ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) { if (attr->offset != offset) { continue; } @@ -1905,7 +1905,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables) ht = zend_array_dup(fptr->op_array.static_variables); ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht); } - ZEND_HASH_FOREACH_VAL(ht, val) { + ZEND_HASH_MAP_FOREACH_VAL(ht, val) { if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) { RETURN_THROWS(); } @@ -3954,7 +3954,7 @@ static void add_class_vars(zend_class_entry *ce, bool statics, zval *return_valu zval *prop, prop_copy; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { if (((prop_info->flags & ZEND_ACC_PRIVATE) && prop_info->ce != ce)) { continue; @@ -4012,7 +4012,7 @@ ZEND_METHOD(ReflectionClass, getStaticProperties) array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { if (((prop_info->flags & ZEND_ACC_PRIVATE) && prop_info->ce != ce)) { continue; @@ -4404,7 +4404,7 @@ ZEND_METHOD(ReflectionClass, getMethods) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { _addmethod(mptr, ce, Z_ARRVAL_P(return_value), filter); } ZEND_HASH_FOREACH_END(); @@ -4580,14 +4580,14 @@ ZEND_METHOD(ReflectionClass, getProperties) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { _addproperty(prop_info, key, ce, Z_ARRVAL_P(return_value), filter); } ZEND_HASH_FOREACH_END(); if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0) { HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj)); zval *prop; - ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) { _adddynproperty(prop, key, ce, return_value); } ZEND_HASH_FOREACH_END(); } @@ -4636,7 +4636,7 @@ ZEND_METHOD(ReflectionClass, getConstants) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, constant) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, constant) { if (UNEXPECTED(zval_update_constant_ex(&constant->value, ce) != SUCCESS)) { RETURN_THROWS(); } @@ -4670,7 +4670,7 @@ ZEND_METHOD(ReflectionClass, getReflectionConstants) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), name, constant) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), name, constant) { if (ZEND_CLASS_CONST_FLAGS(constant) & filter) { zval class_const; reflection_class_constant_factory(name, constant, &class_const); @@ -4695,7 +4695,7 @@ ZEND_METHOD(ReflectionClass, getConstant) GET_REFLECTION_OBJECT_PTR(ce); constants_table = CE_CONSTANTS_TABLE(ce); - ZEND_HASH_FOREACH_PTR(constants_table, c) { + ZEND_HASH_MAP_FOREACH_PTR(constants_table, c) { if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) { RETURN_THROWS(); } @@ -5919,7 +5919,7 @@ ZEND_METHOD(ReflectionExtension, getFunctions) GET_REFLECTION_OBJECT_PTR(module); array_init(return_value); - ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) { + ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), fptr) { if (fptr->common.type==ZEND_INTERNAL_FUNCTION && fptr->internal_function.module == module) { reflection_function_factory(fptr, NULL, &function); @@ -5942,7 +5942,7 @@ ZEND_METHOD(ReflectionExtension, getConstants) GET_REFLECTION_OBJECT_PTR(module); array_init(return_value); - ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) { + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) { if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) { zval const_val; ZVAL_COPY_OR_DUP(&const_val, &constant->value); @@ -5980,7 +5980,7 @@ ZEND_METHOD(ReflectionExtension, getINIEntries) GET_REFLECTION_OBJECT_PTR(module); array_init(return_value); - ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), ini_entry) { _addinientry(ini_entry, return_value, module->module_number); } ZEND_HASH_FOREACH_END(); } @@ -6024,7 +6024,7 @@ ZEND_METHOD(ReflectionExtension, getClasses) GET_REFLECTION_OBJECT_PTR(module); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { add_extension_class(ce, key, return_value, module, 1); } ZEND_HASH_FOREACH_END(); } @@ -6044,7 +6044,7 @@ ZEND_METHOD(ReflectionExtension, getClassNames) GET_REFLECTION_OBJECT_PTR(module); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { add_extension_class(ce, key, return_value, module, 0); } ZEND_HASH_FOREACH_END(); } @@ -6777,7 +6777,7 @@ ZEND_METHOD(ReflectionEnum, getCases) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) { if (ZEND_CLASS_CONST_FLAGS(constant) & ZEND_CLASS_CONST_IS_CASE) { zval class_const; reflection_enum_case_factory(ce, name, constant, &class_const); diff --git a/ext/session/session.c b/ext/session/session.c index 18444932ceb37..32e2f33ae3028 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1727,7 +1727,6 @@ PHP_FUNCTION(session_set_cookie_params) zend_argument_value_error(5, "must be null when argument #1 ($lifetime_or_options) is an array"); RETURN_THROWS(); } - ZEND_HASH_FOREACH_STR_KEY_VAL(options_ht, key, value) { if (key) { ZVAL_DEREF(value); @@ -1986,7 +1985,7 @@ PHP_FUNCTION(session_set_save_handler) /* For compatibility reason, implemented interface is not checked */ /* Find implemented methods - SessionHandlerInterface */ i = 0; - ZEND_HASH_FOREACH_STR_KEY(&php_session_iface_entry->function_table, func_name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_session_iface_entry->function_table, func_name) { if ((current_mptr = zend_hash_find_ptr(&Z_OBJCE_P(obj)->function_table, func_name))) { if (!Z_ISUNDEF(PS(mod_user_names).names[i])) { zval_ptr_dtor(&PS(mod_user_names).names[i]); @@ -2005,7 +2004,7 @@ PHP_FUNCTION(session_set_save_handler) } ZEND_HASH_FOREACH_END(); /* Find implemented methods - SessionIdInterface (optional) */ - ZEND_HASH_FOREACH_STR_KEY(&php_session_id_iface_entry->function_table, func_name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_session_id_iface_entry->function_table, func_name) { if ((current_mptr = zend_hash_find_ptr(&Z_OBJCE_P(obj)->function_table, func_name))) { if (!Z_ISUNDEF(PS(mod_user_names).names[i])) { zval_ptr_dtor(&PS(mod_user_names).names[i]); @@ -2025,7 +2024,7 @@ PHP_FUNCTION(session_set_save_handler) } ZEND_HASH_FOREACH_END(); /* Find implemented methods - SessionUpdateTimestampInterface (optional) */ - ZEND_HASH_FOREACH_STR_KEY(&php_session_update_timestamp_iface_entry->function_table, func_name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_session_update_timestamp_iface_entry->function_table, func_name) { if ((current_mptr = zend_hash_find_ptr(&Z_OBJCE_P(obj)->function_table, func_name))) { if (!Z_ISUNDEF(PS(mod_user_names).names[i])) { zval_ptr_dtor(&PS(mod_user_names).names[i]); diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index ccce7bf1da610..ef3b08730c92d 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -703,12 +703,22 @@ static bool php_snmp_parse_oid( pptr = ZSTR_VAL(type_str); objid_query->vars[objid_query->count].type = *pptr; } else if (type_ht) { - while (idx_type < type_ht->nNumUsed) { - tmp_type = &type_ht->arData[idx_type].val; - if (Z_TYPE_P(tmp_type) != IS_UNDEF) { - break; + if (HT_IS_PACKED(type_ht)) { + while (idx_type < type_ht->nNumUsed) { + tmp_type = &type_ht->arPacked[idx_type]; + if (Z_TYPE_P(tmp_type) != IS_UNDEF) { + break; + } + idx_type++; + } + } else { + while (idx_type < type_ht->nNumUsed) { + tmp_type = &type_ht->arData[idx_type].val; + if (Z_TYPE_P(tmp_type) != IS_UNDEF) { + break; + } + idx_type++; } - idx_type++; } if (idx_type < type_ht->nNumUsed) { convert_to_string(tmp_type); @@ -730,12 +740,22 @@ static bool php_snmp_parse_oid( if (value_str) { objid_query->vars[objid_query->count].value = ZSTR_VAL(value_str); } else if (value_ht) { - while (idx_value < value_ht->nNumUsed) { - tmp_value = &value_ht->arData[idx_value].val; - if (Z_TYPE_P(tmp_value) != IS_UNDEF) { - break; + if (HT_IS_PACKED(value_ht)) { + while (idx_value < value_ht->nNumUsed) { + tmp_value = &value_ht->arPacked[idx_value]; + if (Z_TYPE_P(tmp_value) != IS_UNDEF) { + break; + } + idx_value++; + } + } else { + while (idx_value < value_ht->nNumUsed) { + tmp_value = &value_ht->arData[idx_value].val; + if (Z_TYPE_P(tmp_value) != IS_UNDEF) { + break; + } + idx_value++; } - idx_value++; } if (idx_value < value_ht->nNumUsed) { convert_to_string(tmp_value); @@ -1801,7 +1821,7 @@ static HashTable *php_snmp_get_properties(zend_object *object) obj = php_snmp_fetch_object(object); props = zend_std_get_properties(object); - ZEND_HASH_FOREACH_STR_KEY_PTR(&php_snmp_properties, key, hnd) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&php_snmp_properties, key, hnd) { if (!hnd->read_func || hnd->read_func(obj, &rv) != SUCCESS) { ZVAL_NULL(&rv); } diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 3a4626aa5beee..3b7d6c3885dcb 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -448,7 +448,7 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml zval *tmp; zend_string *type_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(SOAP_GLOBAL(class_map), type_name, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(SOAP_GLOBAL(class_map), type_name, tmp) { ZVAL_DEREF(tmp); if (Z_TYPE_P(tmp) == IS_STRING && ZSTR_LEN(ce->name) == Z_STRLEN_P(tmp) && diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index db3c97b647391..f61357128bfc1 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -823,12 +823,12 @@ int make_http_soap_request(zval *this_ptr, /* Send cookies along with request */ cookies = Z_CLIENT_COOKIES_P(this_ptr); ZEND_ASSERT(Z_TYPE_P(cookies) == IS_ARRAY); - if (zend_hash_num_elements(Z_ARRVAL_P(cookies)) != 0) { + if (zend_hash_num_elements(Z_ARRVAL_P(cookies)) != 0 && !HT_IS_PACKED(Z_ARRVAL_P(cookies))) { zval *data; zend_string *key; has_cookies = 1; smart_str_append_const(&soap_headers, "Cookie: "); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(cookies), key, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(cookies), key, data) { if (key && Z_TYPE_P(data) == IS_ARRAY) { zval *value; diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index e93679a55ea39..68d78326e30ae 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -2287,17 +2287,17 @@ void schema_pass2(sdlCtx *ctx) } ZEND_HASH_FOREACH_END(); } if (ctx->attributeGroups) { - ZEND_HASH_FOREACH_PTR(ctx->attributeGroups, type) { + ZEND_HASH_MAP_FOREACH_PTR(ctx->attributeGroups, type) { schema_type_fixup(ctx, type); } ZEND_HASH_FOREACH_END(); } if (sdl->elements) { - ZEND_HASH_FOREACH_PTR(sdl->elements, type) { + ZEND_HASH_MAP_FOREACH_PTR(sdl->elements, type) { schema_type_fixup(ctx, type); } ZEND_HASH_FOREACH_END(); } if (sdl->groups) { - ZEND_HASH_FOREACH_PTR(sdl->groups, type) { + ZEND_HASH_MAP_FOREACH_PTR(sdl->groups, type) { schema_type_fixup(ctx, type); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 4b79090ee83ff..2049f44821331 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -184,7 +184,7 @@ sdlBindingPtr get_binding_from_type(sdlPtr sdl, sdlBindingType type) return NULL; } - ZEND_HASH_FOREACH_PTR(sdl->bindings, binding) { + ZEND_HASH_MAP_FOREACH_PTR(sdl->bindings, binding) { if (binding->bindingType == type) { return binding; } @@ -1860,7 +1860,7 @@ static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoder sdlExtraAttributePtr tmp; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) { sdl_serialize_key(key, out); sdl_serialize_string(tmp->ns, out); sdl_serialize_string(tmp->val, out); @@ -1960,7 +1960,7 @@ static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTab sdlRestrictionCharPtr tmp; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) { sdl_serialize_resriction_char(tmp, out); sdl_serialize_key(key, out); } ZEND_HASH_FOREACH_END(); @@ -2069,7 +2069,7 @@ static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTabl sdlSoapBindingFunctionHeaderPtr tmp; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(body->headers, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(body->headers, key, tmp) { sdl_serialize_key(key, out); WSDL_CACHE_PUT_1(tmp->use, out); if (tmp->use == SOAP_ENCODED) { @@ -2089,7 +2089,7 @@ static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTabl sdlSoapBindingFunctionHeaderPtr tmp2; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(body->headers, key, tmp2) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(body->headers, key, tmp2) { sdl_serialize_key(key, out); WSDL_CACHE_PUT_1(tmp2->use, out); if (tmp2->use == SOAP_ENCODED) { @@ -2147,7 +2147,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s sdlTypePtr tmp; zval zv; - ZEND_HASH_FOREACH_PTR(sdl->groups, tmp) { + ZEND_HASH_MAP_FOREACH_PTR(sdl->groups, tmp) { ZVAL_LONG(&zv, type_num); zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv); ++type_num; @@ -2181,7 +2181,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s sdlTypePtr tmp; zval zv; - ZEND_HASH_FOREACH_PTR(sdl->elements, tmp) { + ZEND_HASH_MAP_FOREACH_PTR(sdl->elements, tmp) { ZVAL_LONG(&zv, type_num); zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv); ++type_num; @@ -2218,7 +2218,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s sdlTypePtr tmp; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) { sdl_serialize_key(key, out); sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out); } ZEND_HASH_FOREACH_END(); @@ -2238,7 +2238,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s sdlTypePtr tmp; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) { sdl_serialize_key(key, out); sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out); } ZEND_HASH_FOREACH_END(); @@ -2267,7 +2267,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s zval zv; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) { sdl_serialize_key(key, out); sdl_serialize_string(tmp->name, out); sdl_serialize_string(tmp->location, out); @@ -2295,7 +2295,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s int function_num = 1; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) { sdl_serialize_key(key, out); sdl_serialize_string(tmp->functionName, out); sdl_serialize_string(tmp->requestName, out); @@ -2327,7 +2327,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s WSDL_CACHE_PUT_INT(zend_hash_num_elements(tmp->faults), out); - ZEND_HASH_FOREACH_STR_KEY_PTR(tmp->faults, key, fault) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(tmp->faults, key, fault) { sdl_serialize_key(key, out); sdl_serialize_string(fault->name, out); sdl_serialize_parameters(fault->details, &tmp_encoders, &tmp_types, out); @@ -2364,7 +2364,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s zval *function_num; zend_string *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->requests, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->requests, key, tmp) { function_num = zend_hash_str_find(&tmp_functions, (char*)&tmp, sizeof(tmp)); WSDL_CACHE_PUT_INT(Z_LVAL_P(function_num), out); sdl_serialize_key(key, out); @@ -2444,7 +2444,7 @@ static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashT pheaders = malloc(sizeof(HashTable)); zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(headers, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, tmp) { pheader = malloc(sizeof(sdlSoapBindingFunctionHeader)); memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader)); *pheader = *tmp; @@ -2550,7 +2550,7 @@ static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashT pfaults = malloc(sizeof(HashTable)); zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(faults, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(faults, key, tmp) { pfault = malloc(sizeof(sdlFault)); memset(pfault, 0, sizeof(sdlFault)); *pfault = *tmp; @@ -2624,7 +2624,7 @@ static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashT pattr->extraAttributes = malloc(sizeof(HashTable)); zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) { if (key) { pextra = malloc(sizeof(sdlExtraAttribute)); memset(pextra, 0, sizeof(sdlExtraAttribute)); @@ -2768,7 +2768,7 @@ static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, sdlRestrictionCharPtr tmp, penum; ptype->restrictions->enumeration = malloc(sizeof(HashTable)); zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) { penum = tmp; make_persistent_restriction_char_int(&penum); /* We have to duplicate key emalloc->malloc */ @@ -2953,7 +2953,7 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl) psdl->groups = malloc(sizeof(HashTable)); zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) { ptype = make_persistent_sdl_type(tmp, &ptr_map, &bp_types, &bp_encoders); if (key) { /* We have to duplicate key emalloc->malloc */ @@ -2991,7 +2991,7 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl) psdl->elements = malloc(sizeof(HashTable)); zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) { ptype = make_persistent_sdl_type(tmp, &ptr_map, &bp_types, &bp_encoders); if (key) { /* We have to duplicate key emalloc->malloc */ @@ -3052,7 +3052,7 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl) psdl->bindings = malloc(sizeof(HashTable)); zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1); - ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) { pbind = make_persistent_sdl_binding(tmp, &ptr_map); if (key) { /* We have to duplicate key emalloc->malloc */ @@ -3069,7 +3069,7 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl) sdlFunctionPtr tmp; sdlFunctionPtr pfunc; - ZEND_HASH_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) { pfunc = make_persistent_sdl_function(tmp, &ptr_map); if (key) { /* We have to duplicate key emalloc->malloc */ @@ -3089,7 +3089,7 @@ static sdlPtr make_persistent_sdl(sdlPtr sdl) psdl->requests = malloc(sizeof(HashTable)); zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1); - ZEND_HASH_FOREACH_STR_KEY_VAL(sdl->requests, key, zv) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(sdl->requests, key, zv) { tmp = Z_PTR_P(zv); if ((preq = zend_hash_str_find_ptr(&ptr_map, (char*)&tmp, sizeof(tmp))) == NULL) { assert(0); @@ -3352,7 +3352,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) time_t latest = t; zend_string *latest_key = NULL, *key; - ZEND_HASH_FOREACH_STR_KEY_PTR(SOAP_GLOBAL(mem_cache), key, q) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(SOAP_GLOBAL(mem_cache), key, q) { if (q->time < latest) { latest = q->time; latest_key = key; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index f33aacfff706a..11a4984d02c9c 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -744,25 +744,27 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht) /* {{{ */ } ht2 = Z_ARRVAL_P(tmp); - ZEND_HASH_FOREACH_STR_KEY_VAL(ht2, name, tmp) { - if (name) { - if (zend_string_equals_literal(name, "type_name")) { - if (Z_TYPE_P(tmp) == IS_STRING) { - type_name = Z_STRVAL_P(tmp); - } else if (Z_TYPE_P(tmp) != IS_NULL) { - } - } else if (zend_string_equals_literal(name, "type_ns")) { - if (Z_TYPE_P(tmp) == IS_STRING) { - type_ns = Z_STRVAL_P(tmp); - } else if (Z_TYPE_P(tmp) != IS_NULL) { + if (!HT_IS_PACKED(ht2)) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht2, name, tmp) { + if (name) { + if (zend_string_equals_literal(name, "type_name")) { + if (Z_TYPE_P(tmp) == IS_STRING) { + type_name = Z_STRVAL_P(tmp); + } else if (Z_TYPE_P(tmp) != IS_NULL) { + } + } else if (zend_string_equals_literal(name, "type_ns")) { + if (Z_TYPE_P(tmp) == IS_STRING) { + type_ns = Z_STRVAL_P(tmp); + } else if (Z_TYPE_P(tmp) != IS_NULL) { + } + } else if (zend_string_equals_literal(name, "to_xml")) { + to_xml = tmp; + } else if (zend_string_equals_literal(name, "from_xml")) { + to_zval = tmp; } - } else if (zend_string_equals_literal(name, "to_xml")) { - to_xml = tmp; - } else if (zend_string_equals_literal(name, "from_xml")) { - to_zval = tmp; } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } if (type_name) { smart_str nscat = {0}; @@ -1063,14 +1065,14 @@ PHP_METHOD(SoapServer, getFunctions) } else if (service->soap_functions.ft != NULL) { zval *name; - ZEND_HASH_FOREACH_VAL(service->soap_functions.ft, name) { + ZEND_HASH_MAP_FOREACH_VAL(service->soap_functions.ft, name) { add_next_index_str(return_value, zend_string_copy(Z_STR_P(name))); } ZEND_HASH_FOREACH_END(); } if (ft != NULL) { zend_function *f; - ZEND_HASH_FOREACH_PTR(ft, f) { + ZEND_HASH_MAP_FOREACH_PTR(ft, f) { if ((service->type != SOAP_OBJECT && service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) { add_next_index_str(return_value, zend_string_copy(f->common.function_name)); } @@ -2568,7 +2570,7 @@ PHP_METHOD(SoapClient, __getFunctions) sdlFunctionPtr function; array_init(return_value); - ZEND_HASH_FOREACH_PTR(&sdl->functions, function) { + ZEND_HASH_MAP_FOREACH_PTR(&sdl->functions, function) { function_to_string(function, &buf); add_next_index_stringl(return_value, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)); smart_str_free(&buf); @@ -4091,7 +4093,7 @@ static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr params) /* {{{ */ sdlFunctionPtr tmp; sdlParamPtr param; - ZEND_HASH_FOREACH_PTR(&sdl->functions, tmp) { + ZEND_HASH_MAP_FOREACH_PTR(&sdl->functions, tmp) { if (tmp->binding && tmp->binding->bindingType == BINDING_SOAP) { sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)tmp->bindingAttributes; if (fnb->style == SOAP_DOCUMENT) { diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index a82300114c214..1df6eaa09d659 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -2353,8 +2353,8 @@ PHP_FUNCTION(socket_addrinfo_lookup) memset(&hints, 0, sizeof(hints)); - if (zhints) { - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zhints), key, hint) { + if (zhints && !HT_IS_PACKED(Z_ARRVAL_P(zhints))) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zhints), key, hint) { if (key) { if (zend_string_equals_literal(key, "ai_flags")) { hints.ai_flags = zval_get_long(hint); diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index c6b7e02a00ce7..839e978ec61ad 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -410,7 +410,7 @@ static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_stri return NULL; } - /* We don't use ZEND_HASH_FOREACH here, + /* We don't use ZEND_HASH_MAP_FOREACH here, * because autoloaders may be added/removed during autoloading. */ HashPosition pos; zend_hash_internal_pointer_reset_ex(spl_autoload_functions, &pos); @@ -464,6 +464,7 @@ PHP_FUNCTION(spl_autoload_call) } /* }}} */ #define HT_MOVE_TAIL_TO_HEAD(ht) \ + ZEND_ASSERT(!HT_IS_PACKED(ht)); \ do { \ Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \ memmove((ht)->arData + 1, (ht)->arData, \ @@ -478,7 +479,7 @@ static Bucket *spl_find_registered_function(autoload_func_info *find_alfi) { } autoload_func_info *alfi; - ZEND_HASH_FOREACH_PTR(spl_autoload_functions, alfi) { + ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { if (autoload_func_info_equals(alfi, find_alfi)) { return _p; } @@ -599,7 +600,7 @@ PHP_FUNCTION(spl_autoload_functions) array_init(return_value); if (spl_autoload_functions) { - ZEND_HASH_FOREACH_PTR(spl_autoload_functions, alfi) { + ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { if (alfi->closure) { GC_ADDREF(alfi->closure); add_next_index_object(return_value, alfi->closure); @@ -675,7 +676,7 @@ PHP_MINFO_FUNCTION(spl) array_init(&list); SPL_LIST_CLASSES(&list, 0, 1, ZEND_ACC_INTERFACE) strg = estrdup(""); - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(&list), zv) { + ZEND_HASH_MAP_FOREACH_VAL(Z_ARRVAL_P(&list), zv) { spl_build_class_list_string(zv, &strg); } ZEND_HASH_FOREACH_END(); zend_array_destroy(Z_ARR(list)); @@ -685,7 +686,7 @@ PHP_MINFO_FUNCTION(spl) array_init(&list); SPL_LIST_CLASSES(&list, 0, -1, ZEND_ACC_INTERFACE) strg = estrdup(""); - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(&list), zv) { + ZEND_HASH_MAP_FOREACH_VAL(Z_ARRVAL_P(&list), zv) { spl_build_class_list_string(zv, &strg); } ZEND_HASH_FOREACH_END(); zend_array_destroy(Z_ARR(list)); diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 65d1c518d338d..8daaf0a3f49ac 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1986,10 +1986,17 @@ static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* { uint32_t idx = 0; zval *first; - while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) { - idx++; + if (HT_IS_PACKED(Z_ARRVAL(intern->u.file.current_zval))) { + while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arPacked[idx])) { + idx++; + } + first = &Z_ARRVAL(intern->u.file.current_zval)->arPacked[idx]; + } else { + while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) { + idx++; + } + first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val; } - first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val; return Z_TYPE_P(first) == IS_STRING && Z_STRLEN_P(first) == 0; } return zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 0; diff --git a/ext/standard/array.c b/ext/standard/array.c index 6345dd4ebbadf..8137bfcbd8d79 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1205,6 +1205,12 @@ PHP_FUNCTION(key) } /* }}} */ +static int php_data_compare(const void *f, const void *s) /* {{{ */ +{ + return zend_compare((zval*)f, (zval*)s); +} +/* }}} */ + /* {{{ * proto mixed min(array values) * proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]]) @@ -1224,7 +1230,7 @@ PHP_FUNCTION(min) zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0])); RETURN_THROWS(); } else { - zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare_unstable, 0); + zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_data_compare, 0); if (result) { RETURN_COPY_DEREF(result); } else { @@ -1270,7 +1276,7 @@ PHP_FUNCTION(max) zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0])); RETURN_THROWS(); } else { - zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare_unstable, 1); + zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_data_compare, 1); if (result) { RETURN_COPY_DEREF(result); } else { @@ -1667,7 +1673,10 @@ static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_t zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1710,7 +1719,10 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1751,7 +1763,10 @@ static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_t zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1798,7 +1813,10 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1840,7 +1858,10 @@ static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *s zend_string *var_name; zval *entry, *orig_var, final_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1896,7 +1917,10 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo zend_string *var_name; zval *entry, *orig_var, final_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -1947,7 +1971,10 @@ static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol zend_string *var_name; zval *entry, *orig_var, final_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -2021,7 +2048,10 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab zend_string *var_name; zval *entry, *orig_var, final_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -2291,7 +2321,10 @@ static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -2336,7 +2369,10 @@ static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* zend_string *var_name; zval *entry, *orig_var; - ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) { + if (HT_IS_PACKED(arr)) { + return 0; + } + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(arr, var_name, entry) { if (!var_name) { continue; } @@ -2566,8 +2602,7 @@ PHP_FUNCTION(array_fill) RETURN_THROWS(); } else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) { /* create packed array */ - Bucket *p; - zend_long n; + zval *zv; array_init_size(return_value, (uint32_t)(start_key + num)); zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); @@ -2579,18 +2614,15 @@ PHP_FUNCTION(array_fill) GC_ADDREF_EX(Z_COUNTED_P(val), (uint32_t)num); } - p = Z_ARRVAL_P(return_value)->arData; - n = start_key; + zv = Z_ARRVAL_P(return_value)->arPacked; while (start_key--) { - ZVAL_UNDEF(&p->val); - p++; + ZVAL_UNDEF(zv); + zv++; } while (num--) { - ZVAL_COPY_VALUE(&p->val, val); - p->h = n++; - p->key = NULL; - p++; + ZVAL_COPY_VALUE(zv, val); + zv++; } } else { /* create hash */ @@ -2859,7 +2891,7 @@ PHP_FUNCTION(range) static void php_array_data_shuffle(zval *array) /* {{{ */ { uint32_t idx, j, n_elems; - Bucket *p, temp; + zval *zv, temp; HashTable *hash; zend_long rnd_idx; uint32_t n_left; @@ -2873,13 +2905,29 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ hash = Z_ARRVAL_P(array); n_left = n_elems; + if (!HT_IS_PACKED(hash)) { + if (!HT_HAS_STATIC_KEYS_ONLY(hash)) { + Bucket *p = hash->arData; + uint32_t i = hash->nNumUsed; + + for (; i > 0; p++, i--) { + if (Z_ISUNDEF(p->val)) continue; + if (p->key) { + zend_string_release(p->key); + p->key = NULL; + } + } + } + zend_hash_to_packed(hash); + } + if (EXPECTED(!HT_HAS_ITERATORS(hash))) { if (hash->nNumUsed != hash->nNumOfElements) { for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) { - p = hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; + zv = hash->arPacked + idx; + if (Z_TYPE_P(zv) == IS_UNDEF) continue; if (j != idx) { - hash->arData[j] = *p; + ZVAL_COPY_VALUE(&hash->arPacked[j], zv); } j++; } @@ -2887,9 +2935,9 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ while (--n_left) { rnd_idx = php_mt_rand_range(0, n_left); if (rnd_idx != n_left) { - temp = hash->arData[n_left]; - hash->arData[n_left] = hash->arData[rnd_idx]; - hash->arData[rnd_idx] = temp; + ZVAL_COPY_VALUE(&temp, &hash->arPacked[n_left]); + ZVAL_COPY_VALUE(&hash->arPacked[n_left], &hash->arPacked[rnd_idx]); + ZVAL_COPY_VALUE(&hash->arPacked[rnd_idx], &temp); } } } else { @@ -2897,10 +2945,10 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ if (hash->nNumUsed != hash->nNumOfElements) { for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) { - p = hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; + zv = hash->arPacked + idx; + if (Z_TYPE_P(zv) == IS_UNDEF) continue; if (j != idx) { - hash->arData[j] = *p; + ZVAL_COPY_VALUE(&hash->arPacked[j], zv); if (idx == iter_pos) { zend_hash_iterators_update(hash, idx, j); iter_pos = zend_hash_iterators_lower_pos(hash, iter_pos + 1); @@ -2912,28 +2960,16 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ while (--n_left) { rnd_idx = php_mt_rand_range(0, n_left); if (rnd_idx != n_left) { - temp = hash->arData[n_left]; - hash->arData[n_left] = hash->arData[rnd_idx]; - hash->arData[rnd_idx] = temp; + ZVAL_COPY_VALUE(&temp, &hash->arPacked[n_left]); + ZVAL_COPY_VALUE(&hash->arPacked[n_left], &hash->arPacked[rnd_idx]); + ZVAL_COPY_VALUE(&hash->arPacked[rnd_idx], &temp); zend_hash_iterators_update(hash, (uint32_t)rnd_idx, n_left); } } } hash->nNumUsed = n_elems; hash->nInternalPointer = 0; - - for (j = 0; j < n_elems; j++) { - p = hash->arData + j; - if (p->key) { - zend_string_release_ex(p->key, 0); - } - p->h = j; - p->key = NULL; - } hash->nNextFreeElement = n_elems; - if (!(HT_FLAGS(hash) & HASH_FLAG_PACKED)) { - zend_hash_to_packed(hash); - } } /* }}} */ @@ -2958,7 +2994,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H zend_long num_in; /* Number of entries in the input hashtable */ zend_long pos; /* Current position in the hashtable */ uint32_t idx; - Bucket *p; /* Pointer to hash bucket */ zval *entry; /* Hash entry */ uint32_t iter_pos = zend_hash_iterators_lower_pos(in_hash, 0); @@ -2982,80 +3017,138 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H /* Create and initialize output hash */ zend_hash_init(&out_hash, (length > 0 ? num_in - length : 0) + (replace ? zend_hash_num_elements(replace) : 0), NULL, ZVAL_PTR_DTOR, 0); - /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */ - for (pos = 0, idx = 0; pos < offset && idx < in_hash->nNumUsed; idx++) { - p = in_hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - entry = &p->val; + if (HT_IS_PACKED(in_hash)) { + /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */ + entry = in_hash->arPacked; + for (pos = 0, idx = 0; pos < offset && idx < in_hash->nNumUsed; idx++, entry++) { + if (Z_TYPE_P(entry) == IS_UNDEF) continue; - /* Update output hash depending on key type */ - if (p->key == NULL) { zend_hash_next_index_insert_new(&out_hash, entry); - } else { - zend_hash_add_new(&out_hash, p->key, entry); + if (idx == iter_pos) { + if ((zend_long)idx != pos) { + zend_hash_iterators_update(in_hash, idx, pos); + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); + } + pos++; + } + + /* If hash for removed entries exists, go until offset+length and copy the entries to it */ + if (removed != NULL) { + for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + if (Z_TYPE_P(entry) == IS_UNDEF) continue; + pos++; + Z_TRY_ADDREF_P(entry); + zend_hash_next_index_insert_new(removed, entry); + zend_hash_packed_del_val(in_hash, entry); + } + } else { /* otherwise just skip those entries */ + int pos2 = pos; + + for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + if (Z_TYPE_P(entry) == IS_UNDEF) continue; + pos2++; + zend_hash_packed_del_val(in_hash, entry); + } + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos); + + /* If there are entries to insert.. */ + if (replace) { + ZEND_HASH_FOREACH_VAL(replace, entry) { + Z_TRY_ADDREF_P(entry); + zend_hash_next_index_insert_new(&out_hash, entry); + pos++; + } ZEND_HASH_FOREACH_END(); } - if (idx == iter_pos) { - if ((zend_long)idx != pos) { - zend_hash_iterators_update(in_hash, idx, pos); + + /* Copy the remaining input hash entries to the output hash */ + entry = in_hash->arPacked + idx; + for ( ; idx < in_hash->nNumUsed ; idx++, entry++) { + if (Z_TYPE_P(entry) == IS_UNDEF) continue; + zend_hash_next_index_insert_new(&out_hash, entry); + if (idx == iter_pos) { + if ((zend_long)idx != pos) { + zend_hash_iterators_update(in_hash, idx, pos); + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); } - iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); + pos++; } - pos++; - } + } else { + Bucket *p = in_hash->arData; - /* If hash for removed entries exists, go until offset+length and copy the entries to it */ - if (removed != NULL) { - for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++) { - p = in_hash->arData + idx; + /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */ + for (pos = 0, idx = 0; pos < offset && idx < in_hash->nNumUsed; idx++, p++) { if (Z_TYPE(p->val) == IS_UNDEF) continue; - pos++; entry = &p->val; - Z_TRY_ADDREF_P(entry); + + /* Update output hash depending on key type */ if (p->key == NULL) { - zend_hash_next_index_insert_new(removed, entry); + zend_hash_next_index_insert_new(&out_hash, entry); } else { - zend_hash_add_new(removed, p->key, entry); + zend_hash_add_new(&out_hash, p->key, entry); + } + if (idx == iter_pos) { + if ((zend_long)idx != pos) { + zend_hash_iterators_update(in_hash, idx, pos); + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); } - zend_hash_del_bucket(in_hash, p); + pos++; } - } else { /* otherwise just skip those entries */ - int pos2 = pos; - for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++) { - p = in_hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - pos2++; - zend_hash_del_bucket(in_hash, p); - } - } - iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos); + /* If hash for removed entries exists, go until offset+length and copy the entries to it */ + if (removed != NULL) { + for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + pos++; + entry = &p->val; + Z_TRY_ADDREF_P(entry); + if (p->key == NULL) { + zend_hash_next_index_insert_new(removed, entry); + } else { + zend_hash_add_new(removed, p->key, entry); + } + zend_hash_del_bucket(in_hash, p); + } + } else { /* otherwise just skip those entries */ + int pos2 = pos; - /* If there are entries to insert.. */ - if (replace) { - ZEND_HASH_FOREACH_VAL(replace, entry) { - Z_TRY_ADDREF_P(entry); - zend_hash_next_index_insert_new(&out_hash, entry); - pos++; - } ZEND_HASH_FOREACH_END(); - } + for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + pos2++; + zend_hash_del_bucket(in_hash, p); + } + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos); - /* Copy the remaining input hash entries to the output hash */ - for ( ; idx < in_hash->nNumUsed ; idx++) { - p = in_hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - entry = &p->val; - if (p->key == NULL) { - zend_hash_next_index_insert_new(&out_hash, entry); - } else { - zend_hash_add_new(&out_hash, p->key, entry); + /* If there are entries to insert.. */ + if (replace) { + ZEND_HASH_FOREACH_VAL(replace, entry) { + Z_TRY_ADDREF_P(entry); + zend_hash_next_index_insert_new(&out_hash, entry); + pos++; + } ZEND_HASH_FOREACH_END(); } - if (idx == iter_pos) { - if ((zend_long)idx != pos) { - zend_hash_iterators_update(in_hash, idx, pos); + + /* Copy the remaining input hash entries to the output hash */ + for ( ; idx < in_hash->nNumUsed ; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + entry = &p->val; + if (p->key == NULL) { + zend_hash_next_index_insert_new(&out_hash, entry); + } else { + zend_hash_add_new(&out_hash, p->key, entry); + } + if (idx == iter_pos) { + if ((zend_long)idx != pos) { + zend_hash_iterators_update(in_hash, idx, pos); + } + iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); } - iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1); + pos++; } - pos++; } /* replace HashTable data */ @@ -3114,7 +3207,6 @@ PHP_FUNCTION(array_pop) zval *stack, /* Input stack */ *val; /* Value to be popped */ uint32_t idx; - Bucket *p; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_EX(stack, 0, 1) @@ -3124,27 +3216,52 @@ PHP_FUNCTION(array_pop) return; } - /* Get the last value and copy it into the return value */ - idx = Z_ARRVAL_P(stack)->nNumUsed; - while (1) { - if (idx == 0) { - return; + if (HT_IS_PACKED(Z_ARRVAL_P(stack))) { + /* Get the last value and copy it into the return value */ + idx = Z_ARRVAL_P(stack)->nNumUsed; + while (1) { + if (idx == 0) { + return; + } + idx--; + val = Z_ARRVAL_P(stack)->arPacked + idx; + if (Z_TYPE_P(val) != IS_UNDEF) { + break; + } } - idx--; - p = Z_ARRVAL_P(stack)->arData + idx; - val = &p->val; - if (Z_TYPE_P(val) != IS_UNDEF) { - break; + RETVAL_COPY_DEREF(val); + + if (idx == (Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { + Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; } - } - RETVAL_COPY_DEREF(val); - if (!p->key && (zend_long)p->h == (Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { - Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; - } + /* Delete the last value */ + zend_hash_packed_del_val(Z_ARRVAL_P(stack), val); + } else { + Bucket *p; - /* Delete the last value */ - zend_hash_del_bucket(Z_ARRVAL_P(stack), p); + /* Get the last value and copy it into the return value */ + idx = Z_ARRVAL_P(stack)->nNumUsed; + while (1) { + if (idx == 0) { + return; + } + idx--; + p = Z_ARRVAL_P(stack)->arData + idx; + val = &p->val; + if (Z_TYPE_P(val) != IS_UNDEF) { + break; + } + } + RETVAL_COPY_DEREF(val); + + if (!p->key && (zend_long)p->h == (Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { + Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; + } + + /* Delete the last value */ + zend_hash_del_bucket(Z_ARRVAL_P(stack), p); + } zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); } /* }}} */ @@ -3155,7 +3272,6 @@ PHP_FUNCTION(array_shift) zval *stack, /* Input stack */ *val; /* Value to be popped */ uint32_t idx; - Bucket *p; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_EX(stack, 0, 1) @@ -3165,38 +3281,35 @@ PHP_FUNCTION(array_shift) return; } - /* Get the first value and copy it into the return value */ - idx = 0; - while (1) { - if (idx == Z_ARRVAL_P(stack)->nNumUsed) { - return; - } - p = Z_ARRVAL_P(stack)->arData + idx; - val = &p->val; - if (Z_TYPE_P(val) != IS_UNDEF) { - break; - } - idx++; - } - RETVAL_COPY_DEREF(val); - - /* Delete the first value */ - zend_hash_del_bucket(Z_ARRVAL_P(stack), p); - /* re-index like it did before */ - if (HT_FLAGS(Z_ARRVAL_P(stack)) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(Z_ARRVAL_P(stack))) { uint32_t k = 0; + /* Get the first value and copy it into the return value */ + idx = 0; + while (1) { + if (idx == Z_ARRVAL_P(stack)->nNumUsed) { + return; + } + val = Z_ARRVAL_P(stack)->arPacked + idx; + if (Z_TYPE_P(val) != IS_UNDEF) { + break; + } + idx++; + } + RETVAL_COPY_DEREF(val); + + /* Delete the first value */ + zend_hash_packed_del_val(Z_ARRVAL_P(stack), val); + if (EXPECTED(!HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) { for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { - p = Z_ARRVAL_P(stack)->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; + val = Z_ARRVAL_P(stack)->arPacked + idx; + if (Z_TYPE_P(val) == IS_UNDEF) continue; if (idx != k) { - Bucket *q = Z_ARRVAL_P(stack)->arData + k; - q->h = k; - q->key = NULL; - ZVAL_COPY_VALUE(&q->val, &p->val); - ZVAL_UNDEF(&p->val); + zval *q = Z_ARRVAL_P(stack)->arPacked + k; + ZVAL_COPY_VALUE(q, val); + ZVAL_UNDEF(val); } k++; } @@ -3204,14 +3317,12 @@ PHP_FUNCTION(array_shift) uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0); for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { - p = Z_ARRVAL_P(stack)->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; + val = Z_ARRVAL_P(stack)->arPacked + idx; + if (Z_TYPE_P(val) == IS_UNDEF) continue; if (idx != k) { - Bucket *q = Z_ARRVAL_P(stack)->arData + k; - q->h = k; - q->key = NULL; - ZVAL_COPY_VALUE(&q->val, &p->val); - ZVAL_UNDEF(&p->val); + zval *q = Z_ARRVAL_P(stack)->arPacked + k; + ZVAL_COPY_VALUE(q, val); + ZVAL_UNDEF(val); if (idx == iter_pos) { zend_hash_iterators_update(Z_ARRVAL_P(stack), idx, k); iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1); @@ -3225,6 +3336,25 @@ PHP_FUNCTION(array_shift) } else { uint32_t k = 0; int should_rehash = 0; + Bucket *p; + + /* Get the first value and copy it into the return value */ + idx = 0; + while (1) { + if (idx == Z_ARRVAL_P(stack)->nNumUsed) { + return; + } + p = Z_ARRVAL_P(stack)->arData + idx; + val = &p->val; + if (Z_TYPE_P(val) != IS_UNDEF) { + break; + } + idx++; + } + RETVAL_COPY_DEREF(val); + + /* Delete the first value */ + zend_hash_del_bucket(Z_ARRVAL_P(stack), p); for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { p = Z_ARRVAL_P(stack)->arData + idx; @@ -3380,7 +3510,7 @@ static inline Bucket* find_bucket_at_offset(HashTable* ht, zend_long offset) } /* Otherwise, this code has to iterate over the HashTable and skip holes in the array. */ pos = 0; - ZEND_HASH_FOREACH_BUCKET(ht, bucket) { + ZEND_HASH_MAP_FOREACH_BUCKET(ht, bucket) { if (pos >= offset) { /* This is the bucket of the array element at the requested offset */ return bucket; @@ -3393,6 +3523,33 @@ static inline Bucket* find_bucket_at_offset(HashTable* ht, zend_long offset) } /* }}} */ +/* {{{ find_bucket_at_offset(HashTable* ht, zend_long offset) + Finds the bucket at the given valid offset */ +static inline zval* find_packed_val_at_offset(HashTable* ht, zend_long offset) +{ + zend_long pos; + zval *zv; + ZEND_ASSERT(offset >= 0 && offset <= ht->nNumOfElements); + if (HT_IS_WITHOUT_HOLES(ht)) { + /* There's no need to iterate over the array to filter out holes if there are no holes */ + /* This properly handles both packed and unpacked arrays. */ + return ht->arPacked + offset; + } + /* Otherwise, this code has to iterate over the HashTable and skip holes in the array. */ + pos = 0; + ZEND_HASH_PACKED_FOREACH_VAL(ht, zv) { + if (pos >= offset) { + /* This is the bucket of the array element at the requested offset */ + return zv; + } + ++pos; + } ZEND_HASH_FOREACH_END(); + + /* Return a pointer to the end of the bucket array. */ + return ht->arPacked + ht->nNumUsed; +} +/* }}} */ + /* {{{ Returns elements specified by offset and length */ PHP_FUNCTION(array_slice) { @@ -3446,34 +3603,57 @@ PHP_FUNCTION(array_slice) // Contains modified variants of ZEND_HASH_FOREACH_VAL { HashTable *ht = Z_ARRVAL_P(input); - Bucket *p = find_bucket_at_offset(ht, offset); - Bucket *end = ht->arData + ht->nNumUsed; /* Start at the beginning and go until we hit offset */ - if (HT_IS_PACKED(Z_ARRVAL_P(input)) && - (!preserve_keys || - (offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) { - - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (; p != end; p++) { - if (__fill_idx >= length) { - break; + if (HT_IS_PACKED(ht)) { + zval *zv = find_packed_val_at_offset(ht, offset); + zval *end = ht->arPacked + ht->nNumUsed; + + if (!preserve_keys + || (offset == 0 && HT_IS_WITHOUT_HOLES(ht))) { + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; zv != end; zv++) { + if (__fill_idx >= length) { + break; + } + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) { + continue; + } + entry = zv; + if (UNEXPECTED(Z_ISREF_P(entry)) && + UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { + entry = Z_REFVAL_P(entry); + } + Z_TRY_ADDREF_P(entry); + ZEND_HASH_FILL_ADD(entry); } - entry = &p->val; - if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { + } ZEND_HASH_FILL_END(); + } else { + zend_long n = 0; /* Current number of elements */ + zend_long idx = zv - ht->arPacked; + + for (; zv != end; zv++, idx++) { + if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) { continue; } - if (UNEXPECTED(Z_ISREF_P(entry)) && - UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { - entry = Z_REFVAL_P(entry); + if (n >= length) { + break; } - Z_TRY_ADDREF_P(entry); - ZEND_HASH_FILL_ADD(entry); + n++; + if (preserve_keys) { + entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, zv); + } else { + entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), zv); + } + zval_add_ref(entry); } - } ZEND_HASH_FILL_END(); + } } else { zend_long n = 0; /* Current number of elements */ + Bucket *p = find_bucket_at_offset(ht, offset); + Bucket *end = ht->arData + ht->nNumUsed; + for (; p != end; p++) { entry = &p->val; if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { @@ -3574,10 +3754,10 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src) /* {{{ */ zval *src_entry; zend_string *string_key; - if ((HT_FLAGS(dest) & HASH_FLAG_PACKED) && (HT_FLAGS(src) & HASH_FLAG_PACKED)) { + if (HT_IS_PACKED(dest) && HT_IS_PACKED(src)) { zend_hash_extend(dest, zend_hash_num_elements(dest) + zend_hash_num_elements(src), 1); ZEND_HASH_FILL_PACKED(dest) { - ZEND_HASH_FOREACH_VAL(src, src_entry) { + ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) { if (UNEXPECTED(Z_ISREF_P(src_entry)) && UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) { src_entry = Z_REFVAL_P(src_entry); @@ -3749,7 +3929,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET ret = &args[0]; } if (ret) { - if (HT_FLAGS(Z_ARRVAL_P(ret)) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(Z_ARRVAL_P(ret))) { if (HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(ret))) { ZVAL_COPY(return_value, ret); return; @@ -3777,10 +3957,10 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET /* copy first array */ array_init_size(return_value, count); dest = Z_ARRVAL_P(return_value); - if (HT_FLAGS(src) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(src)) { zend_hash_real_init_packed(dest); ZEND_HASH_FILL_PACKED(dest) { - ZEND_HASH_FOREACH_VAL(src, src_entry) { + ZEND_HASH_PACKED_FOREACH_VAL(src, src_entry) { if (UNEXPECTED(Z_ISREF_P(src_entry) && Z_REFCOUNT_P(src_entry) == 1)) { src_entry = Z_REFVAL_P(src_entry); @@ -3792,7 +3972,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET } else { zend_string *string_key; zend_hash_real_init_mixed(dest); - ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(src, string_key, src_entry) { if (UNEXPECTED(Z_ISREF_P(src_entry) && Z_REFCOUNT_P(src_entry) == 1)) { src_entry = Z_REFVAL_P(src_entry); @@ -4170,10 +4350,10 @@ PHP_FUNCTION(array_reverse) /* Initialize return array */ array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input))); - if ((HT_FLAGS(Z_ARRVAL_P(input)) & HASH_FLAG_PACKED) && !preserve_keys) { + if (HT_IS_PACKED(Z_ARRVAL_P(input)) && !preserve_keys) { zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_REVERSE_FOREACH_VAL(Z_ARRVAL_P(input), entry) { + ZEND_HASH_PACKED_REVERSE_FOREACH_VAL(Z_ARRVAL_P(input), entry) { if (UNEXPECTED(Z_ISREF_P(entry) && Z_REFCOUNT_P(entry) == 1)) { entry = Z_REFVAL_P(entry); @@ -4238,7 +4418,7 @@ PHP_FUNCTION(array_pad) } array_init_size(return_value, pad_size_abs); - if (HT_FLAGS(Z_ARRVAL_P(input)) & HASH_FLAG_PACKED) { + if (HT_IS_PACKED(Z_ARRVAL_P(input))) { zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); if (pad_size < 0) { @@ -4250,7 +4430,7 @@ PHP_FUNCTION(array_pad) } ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), value) { + ZEND_HASH_PACKED_FOREACH_VAL(Z_ARRVAL_P(input), value) { Z_TRY_ADDREF_P(value); ZEND_HASH_FILL_ADD(value); } ZEND_HASH_FOREACH_END(); @@ -4270,7 +4450,7 @@ PHP_FUNCTION(array_pad) } } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(input), key, value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(input), key, value) { Z_TRY_ADDREF_P(value); if (key) { zend_hash_add_new(Z_ARRVAL_P(return_value), key, value); @@ -4440,12 +4620,24 @@ PHP_FUNCTION(array_unique) /* create and sort array with pointers to the target_hash buckets */ arTmp = pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT); - for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) { - p = Z_ARRVAL_P(array)->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - arTmp[i].b = *p; - arTmp[i].i = i; - i++; + if (HT_IS_PACKED(Z_ARRVAL_P(array))) { + zval *zv = Z_ARRVAL_P(array)->arPacked; + for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++, zv++) { + if (Z_TYPE_P(zv) == IS_UNDEF) continue; + ZVAL_COPY_VALUE(&arTmp[i].b.val, zv); + arTmp[i].b.h = idx; + arTmp[i].b.key = NULL; + arTmp[i].i = i; + i++; + } + } else { + p = Z_ARRVAL_P(array)->arData; + for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + arTmp[i].b = *p; + arTmp[i].i = i; + i++; + } } ZVAL_UNDEF(&arTmp[i].b.val); zend_sort((void *) arTmp, i, sizeof(struct bucketindex), @@ -4690,10 +4882,21 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), GC_FLAGS(hash) & IS_ARRAY_PERSISTENT); lists[i] = list; ptrs[i] = list; - for (idx = 0; idx < hash->nNumUsed; idx++) { - p = hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - *list++ = *p; + if (HT_IS_PACKED(hash)) { + zval *zv = hash->arPacked; + for (idx = 0; idx < hash->nNumUsed; idx++, zv++) { + if (Z_TYPE_P(zv) == IS_UNDEF) continue; + ZVAL_COPY_VALUE(&list->val, zv); + list->h = idx; + list->key = NULL; + list++; + } + } else { + p = hash->arData; + for (idx = 0; idx < hash->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + *list++ = *p; + } } ZVAL_UNDEF(&list->val); if (hash->nNumOfElements > 1) { @@ -5064,10 +5267,21 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), GC_FLAGS(hash) & IS_ARRAY_PERSISTENT); lists[i] = list; ptrs[i] = list; - for (idx = 0; idx < hash->nNumUsed; idx++) { - p = hash->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - *list++ = *p; + if (HT_IS_PACKED(hash)) { + zval *zv = hash->arPacked; + for (idx = 0; idx < hash->nNumUsed; idx++, zv++) { + if (Z_TYPE_P(zv) == IS_UNDEF) continue; + ZVAL_COPY_VALUE(&list->val, zv); + list->h = idx; + list->key = NULL; + list++; + } + } else { + p = hash->arData; + for (idx = 0; idx < hash->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + *list++ = *p; + } } ZVAL_UNDEF(&list->val); if (hash->nNumOfElements > 1) { @@ -5416,7 +5630,6 @@ PHP_FUNCTION(array_multisort) zval** arrays; Bucket** indirect; uint32_t idx; - Bucket* p; HashTable* hash; int argc; int array_size; @@ -5533,11 +5746,22 @@ PHP_FUNCTION(array_multisort) } for (i = 0; i < num_arrays; i++) { k = 0; - for (idx = 0; idx < Z_ARRVAL_P(arrays[i])->nNumUsed; idx++) { - p = Z_ARRVAL_P(arrays[i])->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - indirect[k][i] = *p; - k++; + if (HT_IS_PACKED(Z_ARRVAL_P(arrays[i]))) { + zval *zv = Z_ARRVAL_P(arrays[i])->arPacked; + for (idx = 0; idx < Z_ARRVAL_P(arrays[i])->nNumUsed; idx++, zv++) { + if (Z_TYPE_P(zv) == IS_UNDEF) continue; + ZVAL_COPY_VALUE(&indirect[k][i].val, zv); + indirect[k][i].h = idx; + indirect[k][i].key = NULL; + k++; + } + } else { + Bucket *p = Z_ARRVAL_P(arrays[i])->arData; + for (idx = 0; idx < Z_ARRVAL_P(arrays[i])->nNumUsed; idx++, p++) { + if (Z_TYPE(p->val) == IS_UNDEF) continue; + indirect[k][i] = *p; + k++; + } } } for (k = 0; k < array_size; k++) { @@ -5550,26 +5774,28 @@ PHP_FUNCTION(array_multisort) /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */ for (i = 0; i < num_arrays; i++) { - int repack; - hash = Z_ARRVAL_P(arrays[i]); hash->nNumUsed = array_size; + hash->nNextFreeElement = array_size; hash->nInternalPointer = 0; - repack = !(HT_FLAGS(hash) & HASH_FLAG_PACKED); + if (HT_IS_PACKED(hash)) { + for (k = 0; k < array_size; k++) { + ZVAL_COPY_VALUE(&hash->arPacked[k], &indirect[k][i].val); + } + } else { + int repack = 1; - for (n = 0, k = 0; k < array_size; k++) { - hash->arData[k] = indirect[k][i]; - if (hash->arData[k].key == NULL) { - hash->arData[k].h = n++; - } else { - repack = 0; + for (n = 0, k = 0; k < array_size; k++) { + hash->arData[k] = indirect[k][i]; + if (hash->arData[k].key == NULL) { + hash->arData[k].h = n++; + } else { + repack = 0; + } + } + if (repack) { + zend_hash_to_packed(hash); } - } - hash->nNextFreeElement = array_size; - if (repack) { - zend_hash_to_packed(hash); - } else if (!(HT_FLAGS(hash) & HASH_FLAG_PACKED)) { - zend_hash_rehash(hash); } } @@ -5634,17 +5860,27 @@ PHP_FUNCTION(array_rand) * The worst case probability of hitting an empty element is 1-1/2. The worst case * probability of hitting N empty elements in a row is (1-1/2)**N. * For N=10 this becomes smaller than 0.1%. */ - do { - zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1); - Bucket *bucket = &ht->arData[randval]; - if (!Z_ISUNDEF(bucket->val)) { - if (bucket->key) { - RETURN_STR_COPY(bucket->key); - } else { - RETURN_LONG(bucket->h); + if (HT_IS_PACKED(ht)) { + do { + zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1); + zval *zv = &ht->arPacked[randval]; + if (!Z_ISUNDEF_P(zv)) { + RETURN_LONG(randval); } - } - } while (1); + } while (1); + } else { + do { + zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1); + Bucket *bucket = &ht->arData[randval]; + if (!Z_ISUNDEF(bucket->val)) { + if (bucket->key) { + RETURN_STR_COPY(bucket->key); + } else { + RETURN_LONG(bucket->h); + } + } + } while (1); + } } if (num_req <= 0 || num_req > num_avail) { @@ -5938,7 +6174,7 @@ PHP_FUNCTION(array_map) } array_init_size(return_value, maxlen); - zend_hash_real_init(Z_ARRVAL_P(return_value), HT_FLAGS(Z_ARRVAL(arrays[0])) & HASH_FLAG_PACKED); + zend_hash_real_init(Z_ARRVAL_P(return_value), HT_IS_PACKED(Z_ARRVAL(arrays[0]))); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, zv) { fci.retval = &result; @@ -5988,18 +6224,31 @@ PHP_FUNCTION(array_map) /* If this array still has elements, add the current one to the * parameter list, otherwise use null value. */ uint32_t pos = array_pos[i]; - while (1) { - if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { - ZVAL_NULL(&zv); - break; - } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { - ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arData[pos].val); - array_pos[i] = pos + 1; - break; + if (HT_IS_PACKED(Z_ARRVAL(arrays[i]))) { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZVAL_NULL(&zv); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arPacked[pos]) != IS_UNDEF) { + ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arPacked[pos]); + array_pos[i] = pos + 1; + break; + } + pos++; + } + } else { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZVAL_NULL(&zv); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { + ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arData[pos].val); + array_pos[i] = pos + 1; + break; + } + pos++; } - pos++; } - zend_hash_next_index_insert_new(Z_ARRVAL(result), &zv); } @@ -6014,16 +6263,30 @@ PHP_FUNCTION(array_map) /* If this array still has elements, add the current one to the * parameter list, otherwise use null value. */ uint32_t pos = array_pos[i]; - while (1) { - if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { - ZVAL_NULL(¶ms[i]); - break; - } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { - ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); - array_pos[i] = pos + 1; - break; + if (HT_IS_PACKED(Z_ARRVAL(arrays[i]))) { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZVAL_NULL(¶ms[i]); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arPacked[pos]) != IS_UNDEF) { + ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arPacked[pos]); + array_pos[i] = pos + 1; + break; + } + pos++; + } + } else { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZVAL_NULL(¶ms[i]); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { + ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); + array_pos[i] = pos + 1; + break; + } + pos++; } - pos++; } } @@ -6198,8 +6461,9 @@ PHP_FUNCTION(array_combine) while (1) { if (pos_values >= values->nNumUsed) { break; - } else if (Z_TYPE(values->arData[pos_values].val) != IS_UNDEF) { - entry_values = &values->arData[pos_values].val; + } + entry_values = ZEND_HASH_ELEMENT(values, pos_values); + if (Z_TYPE_P(entry_values) != IS_UNDEF) { if (Z_TYPE_P(entry_keys) == IS_LONG) { entry_values = zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry_keys), entry_values); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 73d92fd447f19..911e41842fd40 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2015,7 +2015,7 @@ PHP_FUNCTION(ini_get_all) } array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) { zval option; if (module_number != 0 && ini_entry->module_number != module_number) { diff --git a/ext/standard/info.c b/ext/standard/info.c index 395110d25f218..e97faf627a639 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -99,20 +99,22 @@ static ZEND_COLD void php_info_print_stream_hash(const char *name, HashTable *ht php_info_printf("\nRegistered %s => ", name); } - ZEND_HASH_FOREACH_STR_KEY(ht, key) { - if (key) { - if (first) { - first = 0; - } else { - php_info_print(", "); - } - if (!sapi_module.phpinfo_as_text) { - php_info_print_html_esc(ZSTR_VAL(key), ZSTR_LEN(key)); - } else { - php_info_print(ZSTR_VAL(key)); + if (!HT_IS_PACKED(ht)) { + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + if (key) { + if (first) { + first = 0; + } else { + php_info_print(", "); + } + if (!sapi_module.phpinfo_as_text) { + php_info_print_html_esc(ZSTR_VAL(key), ZSTR_LEN(key)); + } else { + php_info_print(ZSTR_VAL(key)); + } } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } if (!sapi_module.phpinfo_as_text) { php_info_print("\n"); @@ -926,7 +928,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag) zend_hash_copy(&sorted_registry, &module_registry, NULL); zend_hash_sort(&sorted_registry, module_name_cmp, 0); - ZEND_HASH_FOREACH_PTR(&sorted_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) { if (module->info_func || module->version) { php_info_print_module(module); } @@ -935,7 +937,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag) SECTION("Additional Modules"); php_info_print_table_start(); php_info_print_table_header(1, "Module Name"); - ZEND_HASH_FOREACH_PTR(&sorted_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) { if (!module->info_func && !module->version) { php_info_print_module(module); } diff --git a/ext/standard/password.c b/ext/standard/password.c index 651cffc9fe656..98b27ff34bd0c 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -678,7 +678,7 @@ PHP_FUNCTION(password_algos) { ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY(&php_password_algos, algo) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&php_password_algos, algo) { add_next_index_str(return_value, zend_string_copy(algo)); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 3dd22956d3a9b..419b49e586f71 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -571,7 +571,7 @@ PHP_FUNCTION(stream_get_transports) stream_xport_hash = php_stream_xport_get_hash(); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY(stream_xport_hash, stream_xport) { + ZEND_HASH_MAP_FOREACH_STR_KEY(stream_xport_hash, stream_xport) { add_next_index_str(return_value, zend_string_copy(stream_xport)); } ZEND_HASH_FOREACH_END(); } @@ -587,7 +587,7 @@ PHP_FUNCTION(stream_get_wrappers) url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash(); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY(url_stream_wrappers_hash, stream_protocol) { + ZEND_HASH_MAP_FOREACH_STR_KEY(url_stream_wrappers_hash, stream_protocol) { if (stream_protocol) { add_next_index_str(return_value, zend_string_copy(stream_protocol)); } @@ -892,11 +892,13 @@ static int parse_context_options(php_stream_context *context, HashTable *options ZEND_HASH_FOREACH_STR_KEY_VAL(options, wkey, wval) { ZVAL_DEREF(wval); if (wkey && Z_TYPE_P(wval) == IS_ARRAY) { - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(wval), okey, oval) { - if (okey) { - php_stream_context_set_option(context, ZSTR_VAL(wkey), ZSTR_VAL(okey), oval); - } - } ZEND_HASH_FOREACH_END(); + if (!HT_IS_PACKED(Z_ARRVAL_P(wval))) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(wval), okey, oval) { + if (okey) { + php_stream_context_set_option(context, ZSTR_VAL(wkey), ZSTR_VAL(okey), oval); + } + } ZEND_HASH_FOREACH_END(); + } } else { zend_value_error("Options should have the form [\"wrappername\"][\"optionname\"] = $value"); return FAILURE; diff --git a/ext/standard/string.c b/ext/standard/string.c index 4608d954d4bd2..0f29cbb038a73 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2352,12 +2352,22 @@ PHP_FUNCTION(substr_replace) zend_string *tmp_repl_str = NULL; if (repl_ht) { repl_idx = 0; - while (repl_idx < repl_ht->nNumUsed) { - tmp_repl = &repl_ht->arData[repl_idx].val; - if (Z_TYPE_P(tmp_repl) != IS_UNDEF) { - break; + if (HT_IS_PACKED(repl_ht)) { + while (repl_idx < repl_ht->nNumUsed) { + tmp_repl = &repl_ht->arPacked[repl_idx]; + if (Z_TYPE_P(tmp_repl) != IS_UNDEF) { + break; + } + repl_idx++; + } + } else { + while (repl_idx < repl_ht->nNumUsed) { + tmp_repl = &repl_ht->arData[repl_idx].val; + if (Z_TYPE_P(tmp_repl) != IS_UNDEF) { + break; + } + repl_idx++; } - repl_idx++; } if (repl_idx < repl_ht->nNumUsed) { repl_str = zval_get_tmp_string(tmp_repl, &tmp_repl_str); @@ -2399,12 +2409,22 @@ PHP_FUNCTION(substr_replace) zend_string *orig_str = zval_get_tmp_string(tmp_str, &tmp_orig_str); if (from_ht) { - while (from_idx < from_ht->nNumUsed) { - tmp_from = &from_ht->arData[from_idx].val; - if (Z_TYPE_P(tmp_from) != IS_UNDEF) { - break; + if (HT_IS_PACKED(from_ht)) { + while (from_idx < from_ht->nNumUsed) { + tmp_from = &from_ht->arPacked[from_idx]; + if (Z_TYPE_P(tmp_from) != IS_UNDEF) { + break; + } + from_idx++; + } + } else { + while (from_idx < from_ht->nNumUsed) { + tmp_from = &from_ht->arData[from_idx].val; + if (Z_TYPE_P(tmp_from) != IS_UNDEF) { + break; + } + from_idx++; } - from_idx++; } if (from_idx < from_ht->nNumUsed) { f = zval_get_long(tmp_from); @@ -2434,12 +2454,22 @@ PHP_FUNCTION(substr_replace) } if (len_ht) { - while (len_idx < len_ht->nNumUsed) { - tmp_len = &len_ht->arData[len_idx].val; - if (Z_TYPE_P(tmp_len) != IS_UNDEF) { - break; + if (HT_IS_PACKED(len_ht)) { + while (len_idx < len_ht->nNumUsed) { + tmp_len = &len_ht->arPacked[len_idx]; + if (Z_TYPE_P(tmp_len) != IS_UNDEF) { + break; + } + len_idx++; + } + } else { + while (len_idx < len_ht->nNumUsed) { + tmp_len = &len_ht->arData[len_idx].val; + if (Z_TYPE_P(tmp_len) != IS_UNDEF) { + break; + } + len_idx++; } - len_idx++; } if (len_idx < len_ht->nNumUsed) { l = zval_get_long(tmp_len); @@ -2469,12 +2499,22 @@ PHP_FUNCTION(substr_replace) result_len = ZSTR_LEN(orig_str) - l; if (repl_ht) { - while (repl_idx < repl_ht->nNumUsed) { - tmp_repl = &repl_ht->arData[repl_idx].val; - if (repl_ht != IS_UNDEF) { - break; + if (HT_IS_PACKED(repl_ht)) { + while (repl_idx < repl_ht->nNumUsed) { + tmp_repl = &repl_ht->arPacked[repl_idx]; + if (repl_ht != IS_UNDEF) { + break; + } + repl_idx++; + } + } else { + while (repl_idx < repl_ht->nNumUsed) { + tmp_repl = &repl_ht->arData[repl_idx].val; + if (repl_ht != IS_UNDEF) { + break; + } + repl_idx++; } - repl_idx++; } if (repl_idx < repl_ht->nNumUsed) { zend_string *tmp_repl_str; @@ -4157,12 +4197,22 @@ static zend_long php_str_replace_in_subject( if (replace_ht) { /* Get current entry */ zval *replace_entry = NULL; - while (replace_idx < replace_ht->nNumUsed) { - replace_entry = &replace_ht->arData[replace_idx].val; - if (Z_TYPE_P(replace_entry) != IS_UNDEF) { - break; + if (HT_IS_PACKED(replace_ht)) { + while (replace_idx < replace_ht->nNumUsed) { + replace_entry = &replace_ht->arPacked[replace_idx]; + if (Z_TYPE_P(replace_entry) != IS_UNDEF) { + break; + } + replace_idx++; + } + } else { + while (replace_idx < replace_ht->nNumUsed) { + replace_entry = &replace_ht->arData[replace_idx].val; + if (Z_TYPE_P(replace_entry) != IS_UNDEF) { + break; + } + replace_idx++; } - replace_idx++; } if (replace_idx < replace_ht->nNumUsed) { /* Make sure we're dealing with strings. */ diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 9bfd85c6518e5..dcbfc381d295f 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -497,8 +497,8 @@ PHP_FUNCTION(stream_get_filters) filters_hash = php_get_stream_filters_hash(); - if (filters_hash) { - ZEND_HASH_FOREACH_STR_KEY(filters_hash, filter_name) { + if (filters_hash && !HT_IS_PACKED(filters_hash)) { + ZEND_HASH_MAP_FOREACH_STR_KEY(filters_hash, filter_name) { if (filter_name) { add_next_index_str(return_value, zend_string_copy(filter_name)); } diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index acf73b8a7c68b..4ed51ab3127fe 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -774,13 +774,14 @@ static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options) zval *opt_val; zend_string *opt_name; - ZEND_HASH_FOREACH_STR_KEY_VAL(ht_options, opt_name, opt_val) { - if (opt_name == NULL) { - continue; - } - _php_tidy_set_tidy_opt(doc, ZSTR_VAL(opt_name), opt_val); - } ZEND_HASH_FOREACH_END(); - + if (!HT_IS_PACKED(ht_options)) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht_options, opt_name, opt_val) { + if (opt_name == NULL) { + continue; + } + _php_tidy_set_tidy_opt(doc, ZSTR_VAL(opt_name), opt_val); + } ZEND_HASH_FOREACH_END(); + } return SUCCESS; } diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index bb52f75ac2c2d..c62c0a13ceaec 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -65,7 +65,7 @@ static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params) params = (char **)safe_emalloc((2 * zend_hash_num_elements(parht) + 1), sizeof(char *), 0); memset((char *)params, 0, parsize); - ZEND_HASH_FOREACH_STR_KEY_VAL(parht, string_key, value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(parht, string_key, value) { ZEND_ASSERT(string_key != NULL); if (Z_TYPE_P(value) != IS_STRING) { if (!try_convert_to_string(value)) { diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index ca040b52e2b36..e54c497624794 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -993,7 +993,7 @@ static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */ return NULL; } - ZEND_HASH_FOREACH_STR_KEY_PTR(obj->prop_handler, key, hnd) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(obj->prop_handler, key, hnd) { zval *ret, val; ret = php_zip_property_reader(obj, hnd, &val); if (ret == NULL) { diff --git a/main/output.c b/main/output.c index 3efc0294f85b8..3e29f8f152673 100644 --- a/main/output.c +++ b/main/output.c @@ -560,7 +560,7 @@ PHPAPI int php_output_handler_start(php_output_handler *handler) } } if (NULL != (rconflicts = zend_hash_find_ptr(&php_output_handler_reverse_conflicts, handler->name))) { - ZEND_HASH_FOREACH_PTR(rconflicts, conflict) { + ZEND_HASH_PACKED_FOREACH_PTR(rconflicts, conflict) { if (SUCCESS != conflict(ZSTR_VAL(handler->name), ZSTR_LEN(handler->name))) { return FAILURE; } diff --git a/main/php_ini.c b/main/php_ini.c index fd6f366488212..c41da5b432c38 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -125,7 +125,7 @@ PHPAPI ZEND_COLD void display_ini_entries(zend_module_entry *module) module_number = 0; } - ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), ini_entry) { if (ini_entry->module_number != module_number) { continue; } @@ -812,7 +812,7 @@ PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int zval *data; /* Walk through config hash and alter matching ini entries using the values found in the hash */ - ZEND_HASH_FOREACH_STR_KEY_VAL(source_hash, str, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(source_hash, str, data) { zend_string *data_str = zend_string_dup(Z_STR_P(data), 0); zend_alter_ini_entry_ex(str, data_str, modify_type, stage, 0); zend_string_release(data_str); diff --git a/main/rfc1867.c b/main/rfc1867.c index aaafbd4c5fc9d..a242e04bf3f11 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -191,7 +191,7 @@ PHPAPI void destroy_uploaded_files_hash(void) /* {{{ */ { zval *el; - ZEND_HASH_FOREACH_VAL(SG(rfc1867_uploaded_files), el) { + ZEND_HASH_MAP_FOREACH_VAL(SG(rfc1867_uploaded_files), el) { zend_string *filename = Z_STR_P(el); VCWD_UNLINK(ZSTR_VAL(filename)); } ZEND_HASH_FOREACH_END(); diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c index 4ce90c0a1ba4c..e051964a81591 100644 --- a/sapi/apache2handler/apache_config.c +++ b/sapi/apache2handler/apache_config.c @@ -157,7 +157,7 @@ void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf) n = create_php_config(p, "merge_php_config"); /* copy old config */ #ifdef ZTS - ZEND_HASH_FOREACH_STR_KEY_VAL(&d->config, str, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&d->config, str, data) { zend_string *key; zval *new_entry; @@ -195,7 +195,7 @@ void apply_config(void *dummy) zend_string *str; php_dir_entry *data; - ZEND_HASH_FOREACH_STR_KEY_PTR(&d->config, str, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&d->config, str, data) { phpapdebug((stderr, "APPLYING (%s)(%s)\n", ZSTR_VAL(str), data->value)); if (zend_alter_ini_entry_chars(str, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) { phpapdebug((stderr, "..FAILED\n")); diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 178b6f3de479a..7933e6accea38 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -562,7 +562,7 @@ typedef struct { zend_string *str; php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php_module); - ZEND_HASH_FOREACH_STR_KEY(&c->config, str) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&c->config, str) { zend_restore_ini_entry(str, ZEND_INI_STAGE_SHUTDOWN); } ZEND_HASH_FOREACH_END(); } diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 499a7932bed17..75511ef3bd701 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -254,7 +254,7 @@ static void print_modules(void) zend_hash_init(&sorted_registry, 64, NULL, NULL, 1); zend_hash_copy(&sorted_registry, &module_registry, NULL); zend_hash_sort(&sorted_registry, module_name_cmp, 0); - ZEND_HASH_FOREACH_PTR(&sorted_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) { php_printf("%s\n", module->name); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&sorted_registry); diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 0ad53e813c944..fdd604cec53b0 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -193,7 +193,7 @@ static void print_modules(void) /* {{{ */ zend_hash_init(&sorted_registry, 50, NULL, NULL, 0); zend_hash_copy(&sorted_registry, &module_registry, NULL); zend_hash_sort(&sorted_registry, module_name_cmp, 0); - ZEND_HASH_FOREACH_PTR(&sorted_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) { php_printf("%s\n", module->name); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&sorted_registry); diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 02e0c52088374..55df8b9edac1f 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -398,7 +398,7 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ array_init_size(return_value, zend_hash_num_elements(headers)); - ZEND_HASH_FOREACH_STR_KEY_PTR(headers, key, value) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, value) { ZVAL_STRING(&tmp, value); zend_symtable_update(Z_ARRVAL_P(return_value), key, &tmp); } ZEND_HASH_FOREACH_END(); diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index a8d7f73406e11..657ff72b673a1 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -200,7 +200,7 @@ static void print_modules(void) /* {{{ */ zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); zend_hash_copy(&sorted_registry, &module_registry, NULL); zend_hash_sort(&sorted_registry, module_name_cmp, 0); - ZEND_HASH_FOREACH_PTR(&sorted_registry, module) { + ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) { php_printf("%s\n", module->name); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&sorted_registry); diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index e9a5884b728f2..42a2a9c036432 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -538,7 +538,7 @@ PHP_FUNCTION(phpdbg_get_executable) array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { if (func->type == ZEND_USER_FUNCTION) { if (zend_hash_exists(files, func->op_array.filename)) { insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename); @@ -552,10 +552,10 @@ PHP_FUNCTION(phpdbg_get_executable) } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), name, ce) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), name, ce) { if (ce->type == ZEND_USER_CLASS) { if (zend_hash_exists(files, ce->info.user.filename)) { - ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, func) { if (func->type == ZEND_USER_FUNCTION && zend_hash_exists(files, func->op_array.filename)) { insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename); @@ -572,7 +572,7 @@ PHP_FUNCTION(phpdbg_get_executable) } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_STR_KEY(files, name) { + ZEND_HASH_MAP_FOREACH_STR_KEY(files, name) { phpdbg_file_source *source = zend_hash_find_ptr(&PHPDBG_G(file_sources), name); if (source) { phpdbg_oplog_fill_executable( diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 3780c89033553..a79efef4161bd 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -312,7 +312,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, ze if (pending) { zend_string *file; - ZEND_HASH_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) { HashTable *fileht; phpdbg_debug("Compare against loaded %s\n", file); @@ -394,7 +394,7 @@ PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file) /* {{{ */ phpdbg_debug("was compiled: %s\n", file); - ZEND_HASH_FOREACH_STR_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur, fileht) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur, fileht) { phpdbg_debug("check bp: %s\n", cur); phpdbg_resolve_pending_file_break_ex(file, filelen, cur, fileht); @@ -551,7 +551,7 @@ PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array) /* {{{ * return; } - ZEND_HASH_FOREACH_PTR(oplines_table, brake) { + ZEND_HASH_MAP_FOREACH_PTR(oplines_table, brake) { if (phpdbg_resolve_op_array_break(brake, op_array) == SUCCESS) { phpdbg_breakline_t *opline_break; @@ -1095,7 +1095,7 @@ static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execut phpdbg_breakcond_t *bp; int breakpoint = FAILURE; - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], bp) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], bp) { zval retval; const zend_op *orig_opline = EG(current_execute_data)->opline; zend_function *orig_func = EG(current_execute_data)->func; @@ -1449,7 +1449,7 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Function Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], brake) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], brake) { phpdbg_writeln("#%d\t\t%s%s", brake->id, brake->symbol, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1461,10 +1461,10 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Method Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_table) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_table) { phpdbg_breakmethod_t *brake; - ZEND_HASH_FOREACH_PTR(class_table, brake) { + ZEND_HASH_MAP_FOREACH_PTR(class_table, brake) { phpdbg_writeln("#%d\t\t%s::%s%s", brake->id, brake->class_name, brake->func_name, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1477,10 +1477,10 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("File Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], points) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], points) { phpdbg_breakfile_t *brake; - ZEND_HASH_FOREACH_PTR(points, brake) { + ZEND_HASH_MAP_FOREACH_PTR(points, brake) { phpdbg_writeln("#%d\t\t%s:"ZEND_ULONG_FMT"%s", brake->id, brake->filename, brake->line, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1491,10 +1491,10 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Pending File Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], points) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], points) { phpdbg_breakfile_t *brake; - ZEND_HASH_FOREACH_PTR(points, brake) { + ZEND_HASH_MAP_FOREACH_PTR(points, brake) { phpdbg_writeln("#%d\t\t%s:"ZEND_ULONG_FMT"%s", brake->id, brake->filename, brake->line, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1507,7 +1507,7 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Opline Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], brake) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], brake) { const char *type; switch (brake->type) { case PHPDBG_BREAK_METHOD_OPLINE: @@ -1547,11 +1547,11 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Method opline Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], class_table) { - ZEND_HASH_FOREACH_PTR(class_table, method_table) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], class_table) { + ZEND_HASH_MAP_FOREACH_PTR(class_table, method_table) { phpdbg_breakopline_t *brake; - ZEND_HASH_FOREACH_PTR(method_table, brake) { + ZEND_HASH_MAP_FOREACH_PTR(method_table, brake) { phpdbg_writeln("#%d\t\t%s::%s opline "ZEND_ULONG_FMT"%s", brake->id, brake->class_name, brake->func_name, brake->opline_num, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1565,10 +1565,10 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Function opline Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], function_table) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], function_table) { phpdbg_breakopline_t *brake; - ZEND_HASH_FOREACH_PTR(function_table, brake) { + ZEND_HASH_MAP_FOREACH_PTR(function_table, brake) { phpdbg_writeln("#%d\t\t%s opline "ZEND_ULONG_FMT"%s", brake->id, brake->func_name, brake->opline_num, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1581,10 +1581,10 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("File opline Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], file_table) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], file_table) { phpdbg_breakopline_t *brake; - ZEND_HASH_FOREACH_PTR(file_table, brake) { + ZEND_HASH_MAP_FOREACH_PTR(file_table, brake) { phpdbg_writeln("#%d\t\t%s opline "ZEND_ULONG_FMT"%s", brake->id, brake->class_name, brake->opline_num, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); @@ -1597,7 +1597,7 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Conditional Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], brake) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], brake) { if (brake->paramed) { switch (brake->param.type) { case STR_PARAM: @@ -1653,7 +1653,7 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ phpdbg_out(SEPARATE "\n"); phpdbg_out("Opcode Breakpoints:\n"); - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], brake) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], brake) { phpdbg_writeln("#%d\t\t%s%s", brake->id, brake->name, ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index e63ec89e557dc..0a1e7570a493c 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -69,7 +69,7 @@ PHPDBG_INFO(files) /* {{{ */ } phpdbg_end_try_access(); phpdbg_try_access { - ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), fname) { + ZEND_HASH_MAP_FOREACH_STR_KEY(&EG(included_files), fname) { phpdbg_writeln("File: %s", ZSTR_VAL(fname)); } ZEND_HASH_FOREACH_END(); } phpdbg_catch_access { @@ -105,7 +105,7 @@ PHPDBG_INFO(constants) /* {{{ */ if (EG(zend_constants)) { phpdbg_try_access { - ZEND_HASH_FOREACH_PTR(EG(zend_constants), data) { + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), data) { if (ZEND_CONSTANT_MODULE_NUMBER(data) == PHP_USER_CONSTANT) { zend_hash_update_ptr(&consts, data->name, data); } @@ -119,7 +119,7 @@ PHPDBG_INFO(constants) /* {{{ */ if (zend_hash_num_elements(&consts)) { phpdbg_out("Address Refs Type Constant\n"); - ZEND_HASH_FOREACH_PTR(&consts, data) { + ZEND_HASH_MAP_FOREACH_PTR(&consts, data) { #define VARIABLEINFO(msg, ...) \ phpdbg_writeln( \ @@ -196,7 +196,7 @@ static int phpdbg_print_symbols(bool show_globals) { zend_hash_init(&vars, 8, NULL, NULL, 0); phpdbg_try_access { - ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, var, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(symtable, var, data) { if (zend_is_auto_global(var) ^ !show_globals) { zend_hash_update(&vars, var, data); } @@ -227,7 +227,7 @@ static int phpdbg_print_symbols(bool show_globals) { if (zend_hash_num_elements(&vars)) { phpdbg_out("Address Refs Type Variable\n"); - ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&vars, var, data) { phpdbg_try_access { const char *isref = ""; #define VARIABLEINFO(msg, ...) \ @@ -387,7 +387,7 @@ PHPDBG_INFO(classes) /* {{{ */ zend_hash_init(&classes, 8, NULL, NULL, 0); phpdbg_try_access { - ZEND_HASH_FOREACH_PTR(EG(class_table), ce) { + ZEND_HASH_MAP_FOREACH_PTR(EG(class_table), ce) { if (ce->type == ZEND_USER_CLASS) { zend_hash_next_index_insert_ptr(&classes, ce); } @@ -399,7 +399,7 @@ PHPDBG_INFO(classes) /* {{{ */ phpdbg_notice("User Classes (%d)", zend_hash_num_elements(&classes)); /* once added, assume that classes are stable... until shutdown. */ - ZEND_HASH_FOREACH_PTR(&classes, ce) { + ZEND_HASH_PACKED_FOREACH_PTR(&classes, ce) { phpdbg_print_class_name(ce); if (ce->parent) { @@ -431,7 +431,7 @@ PHPDBG_INFO(funcs) /* {{{ */ zend_hash_init(&functions, 8, NULL, NULL, 0); phpdbg_try_access { - ZEND_HASH_FOREACH_PTR(EG(function_table), zf) { + ZEND_HASH_MAP_FOREACH_PTR(EG(function_table), zf) { if (zf->type == ZEND_USER_FUNCTION) { zend_hash_next_index_insert_ptr(&functions, zf); } @@ -442,7 +442,7 @@ PHPDBG_INFO(funcs) /* {{{ */ phpdbg_notice("User Functions (%d)", zend_hash_num_elements(&functions)); - ZEND_HASH_FOREACH_PTR(&functions, zf) { + ZEND_HASH_PACKED_FOREACH_PTR(&functions, zf) { zend_op_array *op_array = &zf->op_array; phpdbg_write("|-------- %s", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}"); diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index 67d68b9da3588..c28576de3bc9c 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -140,7 +140,7 @@ PHPDBG_PRINT(class) /* {{{ */ if (zend_hash_num_elements(&ce->function_table)) { zend_function *method; - ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, method) { phpdbg_print_function_helper(method); } ZEND_HASH_FOREACH_END(); } @@ -291,7 +291,7 @@ static void phpdbg_print_opcodes_ce(zend_class_entry *ce) { } phpdbg_out("%d methods: ", zend_hash_num_elements(&ce->function_table)); - ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, method) { if (first) { first = 0; } else { @@ -304,7 +304,7 @@ static void phpdbg_print_opcodes_ce(zend_class_entry *ce) { } phpdbg_out("\n"); - ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, method) { phpdbg_print_function_helper(method); } ZEND_HASH_FOREACH_END(); } @@ -332,13 +332,13 @@ void phpdbg_print_opcodes(const char *function) phpdbg_print_opcodes_main(); - ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { if (func->type == ZEND_USER_FUNCTION) { phpdbg_print_opcodes_function(ZSTR_VAL(name), ZSTR_LEN(name)); } } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR(EG(class_table), ce) { + ZEND_HASH_MAP_FOREACH_PTR(EG(class_table), ce) { if (ce->type == ZEND_USER_CLASS) { phpdbg_out("\n"); phpdbg_print_opcodes_ce(ce); diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index 05155bdd069ee..6e7494c931760 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -771,7 +771,7 @@ void phpdbg_automatic_dequeue_free(phpdbg_watch_element *element) { void phpdbg_dequeue_elements_for_recreation(void) { phpdbg_watch_element *element; - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(watch_recreation), element) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(watch_recreation), element) { ZEND_ASSERT(element->flags & (PHPDBG_WATCH_IMPLICIT | PHPDBG_WATCH_RECURSIVE_ROOT | PHPDBG_WATCH_SIMPLE)); if (element->parent || zend_hash_index_find(&PHPDBG_G(watch_free), (zend_ulong) element->parent_container)) { zval _zv, *zv = &_zv; @@ -816,7 +816,7 @@ void phpdbg_remove_watch_element_recursively(phpdbg_watch_element *element) { element->child = NULL; } else if (element->flags & (PHPDBG_WATCH_ARRAY | PHPDBG_WATCH_OBJECT)) { phpdbg_watch_element *child; - ZEND_HASH_FOREACH_PTR(&element->child_container, child) { + ZEND_HASH_MAP_FOREACH_PTR(&element->child_container, child) { phpdbg_remove_watch_element_recursively(child); phpdbg_free_watch_element(child); } ZEND_HASH_FOREACH_END(); @@ -933,11 +933,11 @@ void phpdbg_update_watch_collision_elements(phpdbg_watchpoint_t *watch) { phpdbg_watchpoint_t *parent; phpdbg_watch_element *element; - ZEND_HASH_FOREACH_PTR(&watch->coll->parents, parent) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->coll->parents, parent) { if (parent->coll) { phpdbg_update_watch_collision_elements(parent); } else { - ZEND_HASH_FOREACH_PTR(&parent->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&parent->elements, element) { phpdbg_update_watch_element_watch(element); } ZEND_HASH_FOREACH_END(); } @@ -957,7 +957,7 @@ void phpdbg_remove_watchpoint(phpdbg_watchpoint_t *watch) { } watch->elements.nNumOfElements++; /* dirty hack to avoid double free */ - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { phpdbg_update_watch_element_watch(element); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&watch->elements); @@ -980,7 +980,7 @@ zend_string *phpdbg_watchpoint_change_collision_name(phpdbg_watchpoint_t *watch) phpdbg_watch_element *element; zend_string *name = NULL; if (watch->coll) { - ZEND_HASH_FOREACH_PTR(&watch->coll->parents, parent) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->coll->parents, parent) { if (name) { zend_string_release(name); } @@ -988,7 +988,7 @@ zend_string *phpdbg_watchpoint_change_collision_name(phpdbg_watchpoint_t *watch) } ZEND_HASH_FOREACH_END(); return name; } - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_IMPLICIT) { if ((watch->type == WATCH_ON_ZVAL || watch->type == WATCH_ON_BUCKET) && Z_TYPE(watch->backup.zv) > IS_STRING) { phpdbg_update_watch_element_watch(element->child); @@ -1012,7 +1012,7 @@ void phpdbg_check_watchpoint(phpdbg_watchpoint_t *watch) { zend_string *str; zend_long idx; zval *zv; - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_RECURSIVE) { phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) HT_WATCH_HT(watch)); phpdbg_watch_ht_info *hti = res ? res->ptr : NULL; @@ -1027,7 +1027,7 @@ void phpdbg_check_watchpoint(phpdbg_watchpoint_t *watch) { zend_string_release(str); break; } - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_RECURSIVE) { phpdbg_add_recursive_watch_from_ht(element, idx, str, zv); } @@ -1067,7 +1067,7 @@ void phpdbg_check_watchpoint(phpdbg_watchpoint_t *watch) { phpdbg_watch_element *element = NULL; zval *new; - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { break; } ZEND_HASH_FOREACH_END(); @@ -1107,7 +1107,7 @@ void phpdbg_check_watchpoint(phpdbg_watchpoint_t *watch) { if (watch->type == WATCH_ON_ZVAL || watch->type == WATCH_ON_BUCKET) { phpdbg_watch_element *element; phpdbg_update_watch_ref(watch); - ZEND_HASH_FOREACH_PTR(&watch->elements, element) { + ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_RECURSIVE) { phpdbg_recurse_watch_element(element); } @@ -1122,7 +1122,7 @@ void phpdbg_reenable_memory_watches(void) { phpdbg_btree_result *res; phpdbg_watchpoint_t *watch; - ZEND_HASH_FOREACH_NUM_KEY(PHPDBG_G(watchlist_mem), page) { + ZEND_HASH_MAP_FOREACH_NUM_KEY(PHPDBG_G(watchlist_mem), page) { /* Disable writing again if there are any watchers on that page */ res = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), page + phpdbg_pagesize - 1); if (res) { @@ -1165,7 +1165,7 @@ int phpdbg_print_changed_zvals(void) { mem_list = PHPDBG_G(watchlist_mem); PHPDBG_G(watchlist_mem) = PHPDBG_G(watchlist_mem_backup); - ZEND_HASH_FOREACH_NUM_KEY(mem_list, page) { + ZEND_HASH_MAP_FOREACH_NUM_KEY(mem_list, page) { phpdbg_btree_position pos = phpdbg_btree_find_between(&PHPDBG_G(watchpoint_tree), page, page + phpdbg_pagesize); while ((res = phpdbg_btree_next(&pos))) { @@ -1210,7 +1210,7 @@ void phpdbg_watch_efree(void *ptr) { phpdbg_watch_element *element; phpdbg_watch_ht_info *hti = (phpdbg_watch_ht_info *) watch; - ZEND_HASH_FOREACH_PTR(&hti->watches, element) { + ZEND_HASH_MAP_FOREACH_PTR(&hti->watches, element) { zend_ulong num = zend_hash_num_elements(&hti->watches); phpdbg_remove_watchpoint(element->watch); if (num == 1) { /* prevent access into freed memory */ @@ -1493,7 +1493,7 @@ void phpdbg_destroy_watchpoints(void) { phpdbg_watch_element *element; /* unconditionally free all remaining elements to avoid memory leaks */ - ZEND_HASH_FOREACH_PTR(&PHPDBG_G(watch_recreation), element) { + ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(watch_recreation), element) { phpdbg_automatic_dequeue_free(element); } ZEND_HASH_FOREACH_END(); diff --git a/win32/registry.c b/win32/registry.c index 9aa2005443acf..cd9fc38c199fe 100644 --- a/win32/registry.c +++ b/win32/registry.c @@ -116,7 +116,7 @@ static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_ zend_ulong num; zval *tmpdata; - ZEND_HASH_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) { + ZEND_HASH_MAP_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) { zend_hash_add(ht, index, tmpdata); } ZEND_HASH_FOREACH_END(); } @@ -263,7 +263,7 @@ void UpdateIniFromRegistry(char *path) zend_string *index; zval *data; - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, index, data) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht, index, data) { zend_alter_ini_entry(index, Z_STR_P(data), PHP_INI_USER, PHP_INI_STAGE_ACTIVATE); } ZEND_HASH_FOREACH_END(); }