Skip to content

Commit e86bea8

Browse files
committed
Extend ZEND_HASH_FILL_* API with ZEND_HASH_FILL_GROW and use it to optimize get_declared_classes()
1 parent e10a710 commit e86bea8

File tree

3 files changed

+34
-20
lines changed

3 files changed

+34
-20
lines changed

Zend/zend_builtin_functions.c

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,51 +1257,54 @@ ZEND_FUNCTION(restore_exception_handler)
12571257
}
12581258
/* }}} */
12591259

1260-
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
1260+
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */
12611261
{
12621262
zend_string *key;
1263-
zval *zv, tmp;
1263+
zval *zv;
12641264
zend_class_entry *ce;
12651265

12661266
ZEND_PARSE_PARAMETERS_NONE();
12671267

12681268
array_init(return_value);
1269-
ZEND_HASH_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
1270-
ce = Z_PTR_P(zv);
1271-
if (key
1272-
&& ZSTR_VAL(key)[0] != 0
1273-
&& (ce->ce_flags & flags)
1274-
&& !(ce->ce_flags & skip_flags)) {
1275-
if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) {
1276-
ZVAL_STR_COPY(&tmp, ce->name);
1277-
} else {
1278-
ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR);
1279-
ZVAL_STR_COPY(&tmp, key);
1269+
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
1270+
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
1271+
ZEND_HASH_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
1272+
ce = Z_PTR_P(zv);
1273+
if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags
1274+
&& key
1275+
&& ZSTR_VAL(key)[0] != 0) {
1276+
ZEND_HASH_FILL_GROW();
1277+
if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) {
1278+
ZEND_HASH_FILL_SET_STR_COPY(ce->name);
1279+
} else {
1280+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR);
1281+
ZEND_HASH_FILL_SET_STR_COPY(key);
1282+
}
1283+
ZEND_HASH_FILL_NEXT();
12801284
}
1281-
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1282-
}
1283-
} ZEND_HASH_FOREACH_END();
1285+
} ZEND_HASH_FOREACH_END();
1286+
} ZEND_HASH_FILL_END();
12841287
}
12851288
/* {{{ */
12861289

12871290
/* {{{ Returns an array of all declared traits. */
12881291
ZEND_FUNCTION(get_declared_traits)
12891292
{
1290-
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
1293+
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_TRAIT);
12911294
}
12921295
/* }}} */
12931296

12941297
/* {{{ Returns an array of all declared classes. */
12951298
ZEND_FUNCTION(get_declared_classes)
12961299
{
1297-
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
1300+
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED);
12981301
}
12991302
/* }}} */
13001303

13011304
/* {{{ Returns an array of all declared interfaces. */
13021305
ZEND_FUNCTION(get_declared_interfaces)
13031306
{
1304-
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE, 0);
1307+
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_INTERFACE);
13051308
}
13061309
/* }}} */
13071310

Zend/zend_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2)
300300
return ht;
301301
}
302302

303-
static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
303+
ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
304304
{
305305
HT_ASSERT_RC1(ht);
306306
if (ht->nTableSize >= HT_MAX_SIZE) {

Zend/zend_hash.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht);
112112
ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht);
113113
ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed);
114114
ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed);
115+
ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht);
115116

116117
/* additions/updates/changes */
117118
ZEND_API zval* ZEND_FASTCALL zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag);
@@ -1161,6 +1162,16 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
11611162
uint32_t __fill_idx = __fill_ht->nNumUsed; \
11621163
ZEND_ASSERT(HT_FLAGS(__fill_ht) & HASH_FLAG_PACKED);
11631164

1165+
#define ZEND_HASH_FILL_GROW() do { \
1166+
if (UNEXPECTED(__fill_idx >= __fill_ht->nTableSize)) { \
1167+
__fill_ht->nNumUsed = __fill_idx; \
1168+
__fill_ht->nNumOfElements = __fill_idx; \
1169+
__fill_ht->nNextFreeElement = __fill_idx; \
1170+
zend_hash_packed_grow(__fill_ht); \
1171+
__fill_bkt = __fill_ht->arData + __fill_idx; \
1172+
} \
1173+
} while (0);
1174+
11641175
#define ZEND_HASH_FILL_SET(_val) \
11651176
ZVAL_COPY_VALUE(&__fill_bkt->val, _val)
11661177

0 commit comments

Comments
 (0)