From afa666f65001ec114ee03d31d1a426491da71001 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 20 Jan 2015 21:50:31 +0800 Subject: [PATCH] Optimized range --- ext/standard/array.c | 104 ++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 617392b4e8..58402854f1 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1663,15 +1663,12 @@ PHP_FUNCTION(array_fill_keys) ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) { ZVAL_DEREF(entry); + Z_TRY_ADDREF_P(val); if (Z_TYPE_P(entry) == IS_LONG) { - Z_TRY_ADDREF_P(val); zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val); } else { zend_string *key = zval_get_string(entry); - - Z_TRY_ADDREF_P(val); zend_symtable_update(Z_ARRVAL_P(return_value), key, val); - zend_string_release(key); } } ZEND_HASH_FOREACH_END(); @@ -1705,9 +1702,6 @@ PHP_FUNCTION(range) } } - /* Initialize the return_value as an array. */ - array_init(return_value); - /* If the range is given as strings, generate an array of characters. */ if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) { int type1, type2; @@ -1731,34 +1725,44 @@ PHP_FUNCTION(range) err = 1; goto err; } - for (; low >= high; low -= (unsigned int)lstep) { - if (CG(one_char_string)[low]) { - ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]); - } else { - ZVAL_STRINGL(&tmp, (char*)&low, 1); - } - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - if (((signed int)low - lstep) < 0) { - break; + /* Initialize the return_value as an array. */ + array_init_size(return_value, ((low - high) / lstep) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; low >= high; low -= (unsigned int)lstep) { + if (CG(one_char_string)[low]) { + ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]); + } else { + ZVAL_STRINGL(&tmp, (char*)&low, 1); + } + ZEND_HASH_FILL_ADD(&tmp); + if (((signed int)low - lstep) < 0) { + break; + } } - } + } ZEND_HASH_FILL_END(); } else if (high > low) { /* Positive Steps */ if (lstep <= 0) { err = 1; goto err; } - for (; low <= high; low += (unsigned int)lstep) { - if (CG(one_char_string)[low]) { - ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]); - } else { - ZVAL_STRINGL(&tmp, (char*)&low, 1); - } - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - if (((signed int)low + lstep) > 255) { - break; + array_init_size(return_value, ((high - low) / lstep) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; low <= high; low += (unsigned int)lstep) { + if (CG(one_char_string)[low]) { + ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]); + } else { + ZVAL_STRINGL(&tmp, (char*)&low, 1); + } + ZEND_HASH_FILL_ADD(&tmp); + if (((signed int)low + lstep) > 255) { + break; + } } - } + } ZEND_HASH_FILL_END(); } else { + array_init(return_value); if (CG(one_char_string)[low]) { ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]); } else { @@ -1766,7 +1770,6 @@ PHP_FUNCTION(range) } zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } - } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { double low, high, value; zend_long i; @@ -1782,21 +1785,30 @@ double_str: goto err; } + array_init_size(return_value, ((low - high) / step) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) { Z_DVAL(tmp) = value; - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); + ZEND_HASH_FILL_ADD(&tmp); } + } ZEND_HASH_FILL_END(); } else if (high > low) { /* Positive steps */ if (high - low < step || step <= 0) { err = 1; goto err; } - for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) { - Z_DVAL(tmp) = value; - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - } + array_init_size(return_value, ((high - low) / step) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) { + Z_DVAL(tmp) = value; + ZEND_HASH_FILL_ADD(&tmp); + } + } ZEND_HASH_FILL_END(); } else { + array_init(return_value); Z_DVAL(tmp) = low; zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } @@ -1814,20 +1826,29 @@ long_str: err = 1; goto err; } - for (; low >= high; low -= lstep) { - Z_LVAL(tmp) = (zend_long)low; - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - } + array_init_size(return_value, ((low - high) / lstep) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; low >= high; low -= lstep) { + Z_LVAL(tmp) = (zend_long)low; + ZEND_HASH_FILL_ADD(&tmp); + } + } ZEND_HASH_FILL_END(); } else if (high > low) { /* Positive steps */ if (high - low < lstep || lstep <= 0) { err = 1; goto err; } - for (; low <= high; low += lstep) { - Z_LVAL(tmp) = (zend_long)low; - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - } + array_init_size(return_value, ((high - low) / lstep) + 1); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + for (; low <= high; low += lstep) { + Z_LVAL(tmp) = (zend_long)low; + ZEND_HASH_FILL_ADD(&tmp); + } + } ZEND_HASH_FILL_END(); } else { + array_init(return_value); Z_LVAL(tmp) = (zend_long)low; zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } @@ -1835,7 +1856,6 @@ long_str: err: if (err) { php_error_docref(NULL, E_WARNING, "step exceeds the specified range"); - zval_dtor(return_value); RETURN_FALSE; } } -- 2.40.0