From 82d91d49d839cf611f578df7d6ff013d10926cd8 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 23 Sep 2026 12:55:31 +0800 Subject: [PATCH 1/3] ext/standard: Optimize result-row construction in array_map() with a null callback (#23809) In this case we just init each value once. --- ext/standard/array.c | 195 +++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 91 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index f475eeebf052..4c3704c85106 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -7125,114 +7125,127 @@ PHP_FUNCTION(array_map) } } - array_init_size(return_value, maxlen); - - if (!ZEND_FCI_INITIALIZED(fci)) { - uint32_t *array_pos = ecalloc(n_arrays, sizeof(HashPosition)); - zval zv; - - /* We iterate through all the arrays at once. */ - for (k = 0; k < maxlen; k++) { + if (!maxlen) { + RETURN_EMPTY_ARRAY(); + } - /* If no callback, the result will be an array, consisting of current - * entries from all arrays. */ - array_init_size(&result, n_arrays); + array_init_size(return_value, maxlen); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - for (i = 0; i < n_arrays; i++) { - /* If this array still has elements, add the current one to the - * parameter list, otherwise use null value. */ - uint32_t pos = array_pos[i]; - 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; + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + if (!ZEND_FCI_INITIALIZED(fci)) { + uint32_t *array_pos = ecalloc(n_arrays, sizeof(HashPosition)); + zval zv; + + /* We iterate through all the arrays at once. */ + for (k = 0; k < maxlen; k++) { + + /* If no callback, the result will be an array, consisting of current + * entries from all arrays. */ + array_init_size(&result, n_arrays); + + zend_hash_real_init_packed(Z_ARRVAL(result)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL(result)) { + for (i = 0; i < n_arrays; i++) { + /* If this array still has elements, add the current one to the + * parameter list, otherwise use null value. */ + uint32_t pos = array_pos[i]; + if (HT_IS_PACKED(Z_ARRVAL(arrays[i]))) { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZEND_HASH_FILL_SET_NULL(); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arPacked[pos]) != IS_UNDEF) { + ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arPacked[pos]); + ZEND_HASH_FILL_SET(&zv); + array_pos[i] = pos + 1; + break; + } + pos++; + } + } else { + while (1) { + if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) { + ZEND_HASH_FILL_SET_NULL(); + break; + } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) { + ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arData[pos].val); + ZEND_HASH_FILL_SET(&zv); + array_pos[i] = pos + 1; + break; + } + pos++; + } } - pos++; + ZEND_HASH_FILL_NEXT(); } - } - zend_hash_next_index_insert_new(Z_ARRVAL(result), &zv); - } + } ZEND_HASH_FILL_END(); - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result); - } - - efree(array_pos); - } else { - zval *params = (zval *)safe_emalloc(n_arrays, sizeof(zval), 0); - - /* Remember next starting point in the array, initialize those as zeros. */ - for (i = 0; i < n_arrays; i++) { - Z_EXTRA(params[i]) = 0; - } + ZEND_HASH_FILL_ADD(&result); + } - fci.retval = &result; - fci.param_count = n_arrays; - fci.params = params; + efree(array_pos); + } else { + zval *params = (zval *)safe_emalloc(n_arrays, sizeof(zval), 0); - /* We iterate through all the arrays at once. */ - for (k = 0; k < maxlen; k++) { + /* Remember next starting point in the array, initialize those as zeros. */ for (i = 0; i < n_arrays; i++) { - /* If this array still has elements, add the current one to the - * parameter list, otherwise use null value. */ - uint32_t pos = Z_EXTRA(params[i]); - 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_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arPacked[pos]); - Z_EXTRA(params[i]) = pos + 1; - break; + Z_EXTRA(params[i]) = 0; + } + + fci.retval = &result; + fci.param_count = n_arrays; + fci.params = params; + + /* We iterate through all the arrays at once. */ + for (k = 0; k < maxlen; k++) { + for (i = 0; i < n_arrays; i++) { + /* If this array still has elements, add the current one to the + * parameter list, otherwise use null value. */ + uint32_t pos = Z_EXTRA(params[i]); + 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_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arPacked[pos]); + Z_EXTRA(params[i]) = pos + 1; + break; + } + pos++; } - 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_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); - Z_EXTRA(params[i]) = pos + 1; - break; + } 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_VALUE(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val); + Z_EXTRA(params[i]) = pos + 1; + break; + } + pos++; } - pos++; } } - } - zend_result ret = zend_call_function(&fci, &fci_cache); - ZEND_ASSERT(ret == SUCCESS); - ZEND_IGNORE_VALUE(ret); + zend_result ret = zend_call_function(&fci, &fci_cache); + ZEND_ASSERT(ret == SUCCESS); + ZEND_IGNORE_VALUE(ret); - if (Z_TYPE(result) == IS_UNDEF) { - efree(params); - RETURN_THROWS(); + if (Z_TYPE(result) == IS_UNDEF) { + ZEND_HASH_FILL_FINISH(); + efree(params); + RETURN_THROWS(); + } + + ZEND_HASH_FILL_ADD(&result); } - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result); + efree(params); } - - efree(params); - } + } ZEND_HASH_FILL_END(); } } /* }}} */ From 16130a5c45ef27cb07294c0741574d420383dc67 Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Wed, 23 Sep 2026 09:04:52 +0200 Subject: [PATCH 2/3] [ci-skip] PHP 8.6.0RC1 will be skipped Due to a packaging mistake, API versions weren't properly bumped. --- NEWS | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 108c9ee8fe2c..e5e9e2e8c520 100644 --- a/NEWS +++ b/NEWS @@ -2,15 +2,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.6.0RC2 -- CLI: - . Fixed bug GH-23764 (Built-in server leaks a file descriptor on every HEAD - request for a static file). (jakubskopal) - -- Standard: - . Fixed bug GH-23780 (unserialize('') fails silently). (timwolla) - -24 Sep 2026, PHP 8.6.0RC1 - - Core: . Fixed incorrect internal pointer and foreach iterator positions when compacting arrays with holes. (Weilin Du) @@ -28,6 +19,8 @@ PHP NEWS - CLI . Fix GH-22567 (Windows ZTS CLI SAPI should refresh its TSRMLS cache during request activation). (matyhtf) + . Fixed bug GH-23764 (Built-in server leaks a file descriptor on every HEAD + request for a static file). (jakubskopal) - Date: . Fix unserialization of Time\Duration. (timwolla) @@ -110,6 +103,7 @@ PHP NEWS . Fixed three Windows-only proc_open() defects: an uninitialized PROCESS_INFORMATION, an indeterminate comspec pointer after a failed lookup, and an unchecked CreateFileA() failure. (Ilia Alshanetsky) + . Fixed bug GH-23780 (unserialize('') fails silently). (timwolla) - URI: . Fix casing of enum cases in UriHostType and UrlHostType to match the RFC From b10a60b908eb1ece41198f065c3155b6d566854a Mon Sep 17 00:00:00 2001 From: Shivam Mathur Date: Wed, 23 Sep 2026 08:09:56 +0000 Subject: [PATCH 3/3] Update PHP SDK to 2.8.4 (#23858) --- .github/workflows/test-suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index ce6053f929a0..c9f61e6adfd5 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -853,7 +853,7 @@ jobs: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache PHP_BUILD_OBJ_DIR: C:\obj PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk - PHP_BUILD_SDK_BRANCH: php-sdk-2.8.2 + PHP_BUILD_SDK_BRANCH: php-sdk-2.8.4 PHP_BUILD_CRT: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }} PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }} THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}"