diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 9b4721dbff2..d89c21e1c89 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1257,51 +1257,54 @@ ZEND_FUNCTION(restore_exception_handler) } /* }}} */ -static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */ +static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */ { zend_string *key; - zval *zv, tmp; + zval *zv; zend_class_entry *ce; ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { - ce = Z_PTR_P(zv); - if (key - && ZSTR_VAL(key)[0] != 0 - && (ce->ce_flags & flags) - && !(ce->ce_flags & skip_flags)) { - if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) { - ZVAL_STR_COPY(&tmp, ce->name); - } else { - ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR); - ZVAL_STR_COPY(&tmp, key); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + ZEND_HASH_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) { + ce = Z_PTR_P(zv); + if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags + && key + && ZSTR_VAL(key)[0] != 0) { + ZEND_HASH_FILL_GROW(); + if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) { + ZEND_HASH_FILL_SET_STR_COPY(ce->name); + } else { + ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR); + ZEND_HASH_FILL_SET_STR_COPY(key); + } + ZEND_HASH_FILL_NEXT(); } - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); } /* {{{ */ /* {{{ Returns an array of all declared traits. */ ZEND_FUNCTION(get_declared_traits) { - get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0); + get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_TRAIT); } /* }}} */ /* {{{ Returns an array of all declared classes. */ ZEND_FUNCTION(get_declared_classes) { - get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT); + get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED); } /* }}} */ /* {{{ Returns an array of all declared interfaces. */ ZEND_FUNCTION(get_declared_interfaces) { - get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE, 0); + get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_INTERFACE); } /* }}} */ diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index e52939b1eb5..663630e950b 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -300,7 +300,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2) return ht; } -static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht) +ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht) { HT_ASSERT_RC1(ht); if (ht->nTableSize >= HT_MAX_SIZE) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 25d48f6237c..5b15b7ce494 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -112,6 +112,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht); ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht); ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed); ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed); +ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht); /* additions/updates/changes */ 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, uint32_t __fill_idx = __fill_ht->nNumUsed; \ ZEND_ASSERT(HT_FLAGS(__fill_ht) & HASH_FLAG_PACKED); +#define ZEND_HASH_FILL_GROW() do { \ + if (UNEXPECTED(__fill_idx >= __fill_ht->nTableSize)) { \ + __fill_ht->nNumUsed = __fill_idx; \ + __fill_ht->nNumOfElements = __fill_idx; \ + __fill_ht->nNextFreeElement = __fill_idx; \ + zend_hash_packed_grow(__fill_ht); \ + __fill_bkt = __fill_ht->arData + __fill_idx; \ + } \ + } while (0); + #define ZEND_HASH_FILL_SET(_val) \ ZVAL_COPY_VALUE(&__fill_bkt->val, _val)