]> granicus.if.org Git - php/commitdiff
Optimized array_merge
authorXinchen Hui <laruence@gmail.com>
Tue, 2 Aug 2016 09:39:53 +0000 (17:39 +0800)
committerXinchen Hui <laruence@gmail.com>
Tue, 2 Aug 2016 09:39:53 +0000 (17:39 +0800)
ext/standard/array.c

index 94c39c5855fc8f74d366bfafb1cc6bbf55b49a74..4ad3b68962bdaee97ef512afd80bd1b1538d0cf5 100644 (file)
@@ -3011,8 +3011,12 @@ PHP_FUNCTION(array_slice)
                                if (pos > offset + length) {
                                        break;
                                }
+                               if (UNEXPECTED(Z_ISREF_P(entry))
+                                       && UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) {
+                                       ZVAL_UNREF(entry);
+                               }
+                               Z_TRY_ADDREF_P(entry);
                                ZEND_HASH_FILL_ADD(entry);
-                               zval_add_ref(entry);
                        } ZEND_HASH_FOREACH_END();
                } ZEND_HASH_FILL_END();
        } else {
@@ -3125,24 +3129,32 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src) /* {{{ */
        zval *src_entry;
        zend_string *string_key;
 
-       ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
-               if (Z_REFCOUNTED_P(src_entry)) {
-                       if (UNEXPECTED(Z_ISREF_P(src_entry))
-                        && UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) {
-                               ZVAL_UNREF(src_entry);
-                               if (Z_REFCOUNTED_P(src_entry)) {
-                                       Z_ADDREF_P(src_entry);
+       if ((dest->u.flags & HASH_FLAG_PACKED) && (src->u.flags & HASH_FLAG_PACKED)) {
+               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) {
+                               if (UNEXPECTED(Z_ISREF_P(src_entry)) &&
+                                       UNEXPECTED(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_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
+                       if (UNEXPECTED(Z_ISREF_P(src_entry)) &&
+                               UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) {
+                               ZVAL_UNREF(src_entry);
+                       }
+                       Z_TRY_ADDREF_P(src_entry);
+                       if (string_key) {
+                               zend_hash_update(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_update(dest, string_key, src_entry);
-               } else {
-                       zend_hash_next_index_insert_new(dest, src_entry);
-               }
-       } ZEND_HASH_FOREACH_END();
+               } ZEND_HASH_FOREACH_END();
+       }
        return 1;
 }
 /* }}} */
@@ -3677,8 +3689,12 @@ 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)) {
+                                       ZVAL_UNREF(entry);
+                               }
+                               Z_TRY_ADDREF_P(entry);
                                ZEND_HASH_FILL_ADD(entry);
-                               zval_add_ref(entry);
                        } ZEND_HASH_FOREACH_END();
                } ZEND_HASH_FILL_END();
        } else {