From: Xinchen Hui Date: Tue, 2 Aug 2016 12:02:23 +0000 (+0800) Subject: Optimized array_merge and cleanup X-Git-Tag: php-7.1.0beta2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=70f79fd8b61403aa68c39b3cf4c79ee76462814a;p=php Optimized array_merge and cleanup --- diff --git a/ext/standard/array.c b/ext/standard/array.c index 4ad3b68962..b24c4d4eb2 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3011,8 +3011,8 @@ PHP_FUNCTION(array_slice) if (pos > offset + length) { break; } - if (UNEXPECTED(Z_ISREF_P(entry)) - && UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { + if (UNEXPECTED(Z_ISREF_P(entry)) && + UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { ZVAL_UNREF(entry); } Z_TRY_ADDREF_P(entry); @@ -3143,8 +3143,8 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src) /* {{{ */ } ZEND_HASH_FILL_END(); } else { ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) { - if (UNEXPECTED(Z_ISREF_P(src_entry)) && - UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) { + if (UNEXPECTED(Z_ISREF_P(src_entry) && + Z_REFCOUNT_P(src_entry) == 1)) { ZVAL_UNREF(src_entry); } Z_TRY_ADDREF_P(src_entry); @@ -3230,7 +3230,7 @@ static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETE { zval *args = NULL; zval *arg; - int argc, i, init_size = 0; + int argc, i; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { @@ -3249,98 +3249,79 @@ static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETE if (Z_TYPE_P(arg) != IS_ARRAY) { php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1); RETURN_NULL(); - } else { - int num = zend_hash_num_elements(Z_ARRVAL_P(arg)); - - if (num > init_size) { - init_size = num; - } } } - array_init_size(return_value, init_size); if (replace) { - zend_string *string_key; - zval *src_entry; - zend_ulong idx; - HashTable *src, *dest; + HashTable *dest; /* copy first array */ arg = args; ZVAL_DEREF(arg); - src = Z_ARRVAL_P(arg); - dest = Z_ARRVAL_P(return_value); - ZEND_HASH_FOREACH_KEY_VAL(src, idx, string_key, src_entry) { - if (Z_REFCOUNTED_P(src_entry)) { - if (UNEXPECTED(Z_ISREF_P(src_entry) && Z_REFCOUNT_P(src_entry) == 1)) { - src_entry = Z_REFVAL_P(src_entry); - if (Z_REFCOUNTED_P(src_entry)) { - Z_ADDREF_P(src_entry); - } - } else { - Z_ADDREF_P(src_entry); - } - } - if (string_key) { - zend_hash_add_new(dest, string_key, src_entry); - } else { - zend_hash_index_add_new(dest, idx, src_entry); - } - } ZEND_HASH_FOREACH_END(); - + dest = zend_array_dup(Z_ARRVAL_P(arg)); + ZVAL_ARR(return_value, dest); if (recursive) { for (i = 1; i < argc; i++) { arg = args + i; ZVAL_DEREF(arg); - php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg)); + php_array_replace_recursive(dest, Z_ARRVAL_P(arg)); } } else { for (i = 1; i < argc; i++) { arg = args + i; ZVAL_DEREF(arg); - zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg), zval_add_ref, 1); + zend_hash_merge(dest, Z_ARRVAL_P(arg), zval_add_ref, 1); } } } else { - zend_string *string_key; zval *src_entry; HashTable *src, *dest; - /* copy first array */ arg = args; ZVAL_DEREF(arg); src = Z_ARRVAL_P(arg); + /* copy first array */ + array_init_size(return_value, zend_hash_num_elements(src)); dest = Z_ARRVAL_P(return_value); - ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) { - if (Z_REFCOUNTED_P(src_entry)) { - if (UNEXPECTED(Z_ISREF_P(src_entry) && Z_REFCOUNT_P(src_entry) == 1)) { - src_entry = Z_REFVAL_P(src_entry); - if (Z_REFCOUNTED_P(src_entry)) { - Z_ADDREF_P(src_entry); + if (src->u.flags & HASH_FLAG_PACKED) { + zend_hash_real_init(dest, 1); + ZEND_HASH_FILL_PACKED(dest) { + ZEND_HASH_FOREACH_VAL(src, src_entry) { + if (UNEXPECTED(Z_ISREF_P(src_entry) && + Z_REFCOUNT_P(src_entry) == 1)) { + ZVAL_UNREF(src_entry); } + Z_TRY_ADDREF_P(src_entry); + ZEND_HASH_FILL_ADD(src_entry); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } else { + zend_string *string_key; + ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) { + if (UNEXPECTED(Z_ISREF_P(src_entry) && + Z_REFCOUNT_P(src_entry) == 1)) { + ZVAL_UNREF(src_entry); + } + Z_TRY_ADDREF_P(src_entry); + if (string_key) { + zend_hash_add_new(dest, string_key, src_entry); } else { - Z_ADDREF_P(src_entry); + zend_hash_next_index_insert_new(dest, src_entry); } - } - if (string_key) { - zend_hash_add_new(dest, string_key, src_entry); - } else { - zend_hash_next_index_insert_new(dest, src_entry); - } - } ZEND_HASH_FOREACH_END(); - + } ZEND_HASH_FOREACH_END(); + } if (recursive) { for (i = 1; i < argc; i++) { arg = args + i; ZVAL_DEREF(arg); - php_array_merge_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg)); + php_array_merge_recursive(dest, Z_ARRVAL_P(arg)); } } else { for (i = 1; i < argc; i++) { arg = args + i; ZVAL_DEREF(arg); - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg)); + php_array_merge(dest, Z_ARRVAL_P(arg)); } } } @@ -3689,8 +3670,8 @@ PHP_FUNCTION(array_reverse) zend_hash_real_init(Z_ARRVAL_P(return_value), 1); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { ZEND_HASH_REVERSE_FOREACH_VAL(Z_ARRVAL_P(input), entry) { - if (UNEXPECTED(Z_ISREF_P(entry)) - && UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) { + if (UNEXPECTED(Z_ISREF_P(entry) && + Z_REFCOUNT_P(entry) == 1)) { ZVAL_UNREF(entry); } Z_TRY_ADDREF_P(entry);