diff options
author | Dmitry Stogov <dmitry@zend.com> | 2016-04-07 01:01:11 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2016-04-07 01:01:11 +0300 |
commit | b31240f995a742b363074e0079b1aef4e577a27e (patch) | |
tree | 3c184090aa904d4ae33c4257223c5f03252dd813 | |
parent | 088f55ae74d8cd316fd33f1828f28472409cfb21 (diff) | |
download | php-git-b31240f995a742b363074e0079b1aef4e577a27e.tar.gz |
Optimized array_fill(). This is a perfect function for fast creation of packed arrays.
-rw-r--r-- | ext/standard/array.c | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 289870ac1f..a0cdd91d85 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2000,34 +2000,72 @@ PHP_FUNCTION(array_fill) zval *val; zend_long start_key, num; +#ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "llz", &start_key, &num, &val) == FAILURE) { return; } +#else + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_LONG(start_key) + Z_PARAM_LONG(num) + Z_PARAM_ZVAL(val) + ZEND_PARSE_PARAMETERS_END(); +#endif - if (num < 0) { - php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); - RETURN_FALSE; - } + if (EXPECTED(num > 0)) { + if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) { + php_error_docref(NULL, E_WARNING, "Too many elements"); + RETURN_FALSE; + } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) { + php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied"); + RETURN_FALSE; + } else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) { + /* create packed array */ + Bucket *p; + zend_long n; - /* allocate an array for return */ - array_init_size(return_value, (uint32_t)num); + array_init_size(return_value, (uint32_t)(start_key + num)); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + Z_ARRVAL_P(return_value)->nNumUsed = start_key + num; + Z_ARRVAL_P(return_value)->nNumOfElements = num; + Z_ARRVAL_P(return_value)->nInternalPointer = start_key; - if (num == 0) { - return; - } + if (Z_REFCOUNTED_P(val)) { + GC_REFCOUNT(Z_COUNTED_P(val)) += num; + } - num--; - zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, val); - Z_TRY_ADDREF_P(val); + p = Z_ARRVAL_P(return_value)->arData; + n = start_key; - while (num--) { - if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), val) != NULL) { - Z_TRY_ADDREF_P(val); + while (start_key--) { + ZVAL_UNDEF(&p->val); + p++; + } + while (num--) { + ZVAL_COPY_VALUE(&p->val, val); + p->h = n++; + p->key = NULL; + p++; + } } else { - zval_dtor(return_value); - php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied"); - RETURN_FALSE; + /* create hash */ + array_init_size(return_value, (uint32_t)num); + zend_hash_real_init(Z_ARRVAL_P(return_value), 0); + if (Z_REFCOUNTED_P(val)) { + GC_REFCOUNT(Z_COUNTED_P(val)) += num; + } + zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val); + while (--num) { + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), val); + start_key++; + } } + } else if (EXPECTED(num == 0)) { + array_init(return_value); + return; + } else { + php_error_docref(NULL, E_WARNING, "Number of elements can't be negative"); + RETURN_FALSE; } } /* }}} */ |