Skip to content

Commit 15babe3

Browse files
Move min/max array fallback into array.c
1 parent c076dea commit 15babe3

4 files changed

Lines changed: 76 additions & 75 deletions

File tree

UPGRADING.INTERNALS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES
3535
. The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed.
3636
Call zval_ptr_dtor_nogc() directly instead.
3737
. The internal zend_copy_parameters_array() function is no longer exposed.
38+
. The internal zend_hash_minmax() function is no longer exposed. Scan the
39+
HashTable directly and use zend_compare() for value comparisons instead.
3840
. The zend_make_callable() function has been removed, if a callable zval
3941
needs to be obtained use the zend_get_callable_zval_from_fcc() function
4042
instead. If this was used to store a callable, then an FCC should be

Zend/zend_hash.c

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,73 +3238,6 @@ ZEND_API int zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_fun
32383238
}
32393239

32403240

3241-
ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
3242-
{
3243-
uint32_t idx;
3244-
zval *res;
3245-
3246-
IS_CONSISTENT(ht);
3247-
3248-
if (ht->nNumOfElements == 0 ) {
3249-
return NULL;
3250-
}
3251-
3252-
if (HT_IS_PACKED(ht)) {
3253-
zval *zv;
3254-
3255-
idx = 0;
3256-
while (1) {
3257-
if (idx == ht->nNumUsed) {
3258-
return NULL;
3259-
}
3260-
if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) break;
3261-
idx++;
3262-
}
3263-
res = ht->arPacked + idx;
3264-
for (; idx < ht->nNumUsed; idx++) {
3265-
zv = ht->arPacked + idx;
3266-
if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue;
3267-
3268-
if (flag) {
3269-
if (compar(res, zv) < 0) { /* max */
3270-
res = zv;
3271-
}
3272-
} else {
3273-
if (compar(res, zv) > 0) { /* min */
3274-
res = zv;
3275-
}
3276-
}
3277-
}
3278-
} else {
3279-
Bucket *p;
3280-
3281-
idx = 0;
3282-
while (1) {
3283-
if (idx == ht->nNumUsed) {
3284-
return NULL;
3285-
}
3286-
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
3287-
idx++;
3288-
}
3289-
res = &ht->arData[idx].val;
3290-
for (; idx < ht->nNumUsed; idx++) {
3291-
p = ht->arData + idx;
3292-
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
3293-
3294-
if (flag) {
3295-
if (compar(res, &p->val) < 0) { /* max */
3296-
res = &p->val;
3297-
}
3298-
} else {
3299-
if (compar(res, &p->val) > 0) { /* min */
3300-
res = &p->val;
3301-
}
3302-
}
3303-
}
3304-
}
3305-
return res;
3306-
}
3307-
33083241
ZEND_API bool ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
33093242
{
33103243
const char *tmp = key;

Zend/zend_hash.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,6 @@ typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b);
303303
ZEND_API int zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_func_t compar, bool ordered);
304304
ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber);
305305
ZEND_API void ZEND_FASTCALL zend_array_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber);
306-
ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag);
307-
308306
static zend_always_inline void ZEND_FASTCALL zend_hash_sort(HashTable *ht, bucket_compare_func_t compare_func, bool renumber) {
309307
zend_hash_sort_ex(ht, zend_sort, compare_func, renumber);
310308
}

ext/standard/array.c

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,9 +1089,77 @@ PHP_FUNCTION(key)
10891089
}
10901090
/* }}} */
10911091

1092-
static int php_data_compare(const void *f, const void *s) /* {{{ */
1092+
static zval *php_array_data_minmax(const HashTable *array, bool max) /* {{{ */
10931093
{
1094-
return zend_compare((zval*)f, (zval*)s);
1094+
uint32_t idx;
1095+
zval *res;
1096+
1097+
if (array->nNumOfElements == 0) {
1098+
return NULL;
1099+
}
1100+
1101+
if (HT_IS_PACKED(array)) {
1102+
zval *zv;
1103+
1104+
idx = 0;
1105+
while (1) {
1106+
if (idx == array->nNumUsed) {
1107+
return NULL;
1108+
}
1109+
if (Z_TYPE(array->arPacked[idx]) != IS_UNDEF) {
1110+
break;
1111+
}
1112+
idx++;
1113+
}
1114+
res = array->arPacked + idx;
1115+
for (; idx < array->nNumUsed; idx++) {
1116+
zv = array->arPacked + idx;
1117+
if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) {
1118+
continue;
1119+
}
1120+
1121+
if (max) {
1122+
if (zend_compare(res, zv) < 0) {
1123+
res = zv;
1124+
}
1125+
} else {
1126+
if (zend_compare(res, zv) > 0) {
1127+
res = zv;
1128+
}
1129+
}
1130+
}
1131+
} else {
1132+
Bucket *p;
1133+
1134+
idx = 0;
1135+
while (1) {
1136+
if (idx == array->nNumUsed) {
1137+
return NULL;
1138+
}
1139+
if (Z_TYPE(array->arData[idx].val) != IS_UNDEF) {
1140+
break;
1141+
}
1142+
idx++;
1143+
}
1144+
res = &array->arData[idx].val;
1145+
for (; idx < array->nNumUsed; idx++) {
1146+
p = array->arData + idx;
1147+
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
1148+
continue;
1149+
}
1150+
1151+
if (max) {
1152+
if (zend_compare(res, &p->val) < 0) {
1153+
res = &p->val;
1154+
}
1155+
} else {
1156+
if (zend_compare(res, &p->val) > 0) {
1157+
res = &p->val;
1158+
}
1159+
}
1160+
}
1161+
}
1162+
return res;
10951163
}
10961164
/* }}} */
10971165

@@ -1101,7 +1169,7 @@ static zend_always_inline bool php_array_minmax(HashTable *array, zval *return_v
11011169
zend_long result_lval = 0;
11021170
double result_dval = 0.0;
11031171
/* IS_LONG or IS_DOUBLE while every value scanned so far has that exact type,
1104-
* IS_UNDEF once a value forces the generic php_data_compare() fallback. */
1172+
* IS_UNDEF once a value forces the generic zend_compare() fallback. */
11051173
uint8_t fast_type = IS_UNDEF;
11061174

11071175
ZEND_HASH_FOREACH_VAL(array, entry) {
@@ -1148,7 +1216,7 @@ static zend_always_inline bool php_array_minmax(HashTable *array, zval *return_v
11481216

11491217
fast_type = IS_UNDEF;
11501218

1151-
int cmp = php_data_compare(result, value);
1219+
int cmp = zend_compare(result, value);
11521220
if (max ? cmp < 0 : cmp > 0) {
11531221
result = value;
11541222
}
@@ -1193,7 +1261,7 @@ PHP_FUNCTION(min)
11931261
return;
11941262
}
11951263

1196-
zval *result = zend_hash_minmax(array, php_data_compare, 0);
1264+
zval *result = php_array_data_minmax(array, false);
11971265
if (result) {
11981266
RETURN_COPY_DEREF(result);
11991267
} else {
@@ -1326,7 +1394,7 @@ PHP_FUNCTION(max)
13261394
return;
13271395
}
13281396

1329-
zval *result = zend_hash_minmax(array, php_data_compare, 1);
1397+
zval *result = php_array_data_minmax(array, true);
13301398
if (result) {
13311399
RETURN_COPY_DEREF(result);
13321400
} else {

0 commit comments

Comments
 (0)