Skip to content

Commit 07a4216

Browse files
committed
Implement packed fast-path for array_map()
1 parent 8a61f5c commit 07a4216

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

ext/standard/array.c

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6736,40 +6736,71 @@ PHP_FUNCTION(array_map)
67366736
ZEND_PARSE_PARAMETERS_END();
67376737

67386738
if (n_arrays == 1) {
6739-
zend_ulong num_key;
6740-
zend_string *str_key;
6741-
67426739
if (Z_TYPE(arrays[0]) != IS_ARRAY) {
67436740
zend_argument_type_error(2, "must be of type array, %s given", zend_zval_value_name(&arrays[0]));
67446741
RETURN_THROWS();
67456742
}
6746-
maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0]));
6743+
const HashTable *input = Z_ARRVAL(arrays[0]);
6744+
maxlen = zend_hash_num_elements(input);
67476745

67486746
/* Short-circuit: if no callback and only one array, just return it. */
67496747
if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) {
67506748
ZVAL_COPY(return_value, &arrays[0]);
67516749
return;
67526750
}
67536751

6754-
array_init_size(return_value, maxlen);
6755-
zend_hash_real_init(Z_ARRVAL_P(return_value), HT_IS_PACKED(Z_ARRVAL(arrays[0])));
6752+
HashTable *output;
6753+
if (HT_IS_PACKED(input)) {
6754+
array_init_size(return_value, input->nNumUsed);
6755+
output = Z_ARRVAL_P(return_value);
6756+
zend_hash_real_init_packed(output);
6757+
} else {
6758+
array_init_size(return_value, maxlen);
6759+
output = Z_ARRVAL_P(return_value);
6760+
zend_hash_real_init_mixed(output);
6761+
}
67566762

67576763
fci.retval = &result;
67586764
fci.param_count = 1;
67596765

6760-
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, fci.params) {
6761-
zend_result ret = zend_call_function(&fci, &fci_cache);
6762-
ZEND_ASSERT(ret == SUCCESS);
6763-
if (Z_TYPE(result) == IS_UNDEF) {
6764-
zend_array_destroy(Z_ARR_P(return_value));
6765-
RETURN_NULL();
6766-
}
6767-
if (str_key) {
6768-
_zend_hash_append(Z_ARRVAL_P(return_value), str_key, &result);
6769-
} else {
6770-
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
6771-
}
6772-
} ZEND_HASH_FOREACH_END();
6766+
if (HT_IS_PACKED(input)) {
6767+
uint32_t undefs = 0;
6768+
ZEND_HASH_FILL_PACKED(output) {
6769+
for (zval *cur = input->arPacked, *end = input->arPacked + input->nNumUsed; cur != end; cur++) {
6770+
if (EXPECTED(!Z_ISUNDEF_P(cur))) {
6771+
fci.params = cur;
6772+
zend_result ret = zend_call_function(&fci, &fci_cache);
6773+
ZEND_ASSERT(ret == SUCCESS);
6774+
if (UNEXPECTED(Z_ISUNDEF(result))) {
6775+
ZEND_HASH_FILL_FINISH();
6776+
zend_array_destroy(output);
6777+
RETURN_NULL();
6778+
}
6779+
} else {
6780+
ZVAL_UNDEF(&result);
6781+
undefs++;
6782+
}
6783+
ZEND_HASH_FILL_ADD(&result);
6784+
}
6785+
} ZEND_HASH_FILL_END();
6786+
output->nNumOfElements -= undefs;
6787+
} else {
6788+
zend_ulong num_key;
6789+
zend_string *str_key;
6790+
ZEND_HASH_MAP_FOREACH_KEY_VAL(input, num_key, str_key, fci.params) {
6791+
zend_result ret = zend_call_function(&fci, &fci_cache);
6792+
ZEND_ASSERT(ret == SUCCESS);
6793+
if (UNEXPECTED(Z_ISUNDEF(result))) {
6794+
zend_array_destroy(output);
6795+
RETURN_NULL();
6796+
}
6797+
if (str_key) {
6798+
_zend_hash_append(output, str_key, &result);
6799+
} else {
6800+
zend_hash_index_add_new(output, num_key, &result);
6801+
}
6802+
} ZEND_HASH_FOREACH_END();
6803+
}
67736804
} else {
67746805
uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
67756806

0 commit comments

Comments
 (0)