Skip to content

Commit 9ade78b

Browse files
committed
Refactor code, optimize is_list() in opcache
1 parent f9162a1 commit 9ade78b

File tree

4 files changed

+38
-37
lines changed

4 files changed

+38
-37
lines changed

Zend/zend_hash.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,33 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
11491149
ZEND_HASH_FILL_FINISH(); \
11501150
} while (0)
11511151

1152+
/* Check if an array is a list */
1153+
static zend_always_inline zend_bool zend_array_is_list(zend_array *array)
1154+
{
1155+
zend_long expected_idx = 0;
1156+
zend_long num_idx;
1157+
zend_string* str_idx;
1158+
/* Empty arrays are lists */
1159+
if (zend_hash_num_elements(array) == 0) {
1160+
return 1;
1161+
}
1162+
1163+
/* Packed arrays are lists */
1164+
if (HT_IS_PACKED(array) && HT_IS_WITHOUT_HOLES(array)) {
1165+
return 1;
1166+
}
1167+
1168+
/* Check if the list could theoretically be repacked */
1169+
ZEND_HASH_FOREACH_KEY(array, num_idx, str_idx) {
1170+
if (str_idx != NULL || num_idx != expected_idx++) {
1171+
return 0;
1172+
}
1173+
} ZEND_HASH_FOREACH_END();
1174+
1175+
return 1;
1176+
}
1177+
1178+
11521179
static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, bool interned)
11531180
{
11541181
uint32_t idx = ht->nNumUsed++;

ext/json/json_encoder.c

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,10 @@ static int php_json_escape_string(
3737
static int php_json_determine_array_type(zval *val) /* {{{ */
3838
{
3939
int i;
40-
HashTable *myht = Z_ARRVAL_P(val);
40+
zend_array *myht = Z_ARRVAL_P(val);
4141

42-
i = myht ? zend_hash_num_elements(myht) : 0;
43-
if (i > 0) {
44-
zend_string *key;
45-
zend_ulong index, idx;
46-
47-
if (HT_IS_PACKED(myht) && HT_IS_WITHOUT_HOLES(myht)) {
48-
return PHP_JSON_OUTPUT_ARRAY;
49-
}
50-
51-
idx = 0;
52-
ZEND_HASH_FOREACH_KEY(myht, index, key) {
53-
if (key) {
54-
return PHP_JSON_OUTPUT_OBJECT;
55-
} else {
56-
if (index != idx) {
57-
return PHP_JSON_OUTPUT_OBJECT;
58-
}
59-
}
60-
idx++;
61-
} ZEND_HASH_FOREACH_END();
42+
if (myht) {
43+
return zend_array_is_list(myht) ? PHP_JSON_OUTPUT_ARRAY : PHP_JSON_OUTPUT_OBJECT;
6244
}
6345

6446
return PHP_JSON_OUTPUT_ARRAY;

ext/opcache/Optimizer/sccp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,13 @@ static inline int ct_eval_func_call(
882882
/* pass */
883883
} else if (zend_string_equals_literal(name, "serialize")) {
884884
/* pass */
885+
} else if (zend_string_equals_literal(name, "is_list")) {
886+
if (Z_TYPE_P(args[0]) == IS_ARRAY) {
887+
ZVAL_BOOL(result, zend_array_is_list(Z_ARRVAL_P(args[0])));
888+
} else {
889+
ZVAL_FALSE(result);
890+
}
891+
return SUCCESS;
885892
} else {
886893
return FAILURE;
887894
}

ext/standard/type.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,6 @@ PHP_FUNCTION(is_list)
326326
{
327327
zval *arg;
328328
zend_array *arrval;
329-
zend_ulong num_idx, expected_idx = 0;
330-
zend_string *str_idx;
331329

332330
ZEND_PARSE_PARAMETERS_START(1, 1)
333331
Z_PARAM_ZVAL(arg)
@@ -339,20 +337,7 @@ PHP_FUNCTION(is_list)
339337
arrval = Z_ARRVAL_P(arg);
340338

341339
/* Empty arrays are lists */
342-
if (zend_hash_num_elements(arrval) == 0)
343-
RETURN_TRUE;
344-
345-
/* Packed arrays are lists */
346-
if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval))
347-
RETURN_TRUE;
348-
349-
/* Check if the list could theoretically be repacked */
350-
ZEND_HASH_FOREACH_KEY(arrval, num_idx, str_idx) {
351-
if (str_idx != NULL || num_idx != expected_idx++)
352-
RETURN_FALSE;
353-
} ZEND_HASH_FOREACH_END();
354-
355-
RETURN_TRUE;
340+
RETURN_BOOL(zend_array_is_list(arrval));
356341
}
357342
/* }}} */
358343

0 commit comments

Comments
 (0)