From: Zeev Suraski Date: Thu, 2 Aug 2001 07:00:43 +0000 (+0000) Subject: Avoid going over huge lists of functions, classes and constants. X-Git-Tag: PRE_ENGINE2_SPLIT~131 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c14baeece3d5fed4e20e43dce42ca04ef1f5618a;p=php Avoid going over huge lists of functions, classes and constants. Special thanks to the guys from the MS lab for the profiling tools :) --- diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index cb4ac03333..d76619ccbf 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -54,9 +54,9 @@ void zend_copy_constants(HashTable *target, HashTable *source) static int clean_non_persistent_constant(zend_constant *c TSRMLS_DC) { if (c->flags & CONST_PERSISTENT) { - return 0; + return ZEND_HASH_APPLY_STOP; } else { - return 1; + return ZEND_HASH_APPLY_REMOVE; } } @@ -156,7 +156,7 @@ int zend_shutdown_constants(TSRMLS_D) void clean_non_persistent_constants(TSRMLS_D) { - zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC); + zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC); } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 6ee4fd9634..1c9e42a5e4 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -92,13 +92,21 @@ static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) static int is_not_internal_function(zend_function *function TSRMLS_DC) { - return(function->type != ZEND_INTERNAL_FUNCTION); + if (function->type == ZEND_INTERNAL_FUNCTION) { + return ZEND_HASH_APPLY_STOP; + } else { + return ZEND_HASH_APPLY_REMOVE; + } } static int is_not_internal_class(zend_class_entry *ce TSRMLS_DC) { - return(ce->type != ZEND_INTERNAL_CLASS); + if (ce->type == ZEND_INTERNAL_CLASS) { + return ZEND_HASH_APPLY_STOP; + } else { + return ZEND_HASH_APPLY_REMOVE; + } } @@ -173,8 +181,8 @@ void shutdown_executor(TSRMLS_D) zend_ptr_stack_destroy(&EG(argument_stack)); /* Destroy all op arrays */ - zend_hash_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC); - zend_hash_apply(EG(class_table), (apply_func_t) is_not_internal_class TSRMLS_CC); + zend_hash_reverse_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC); + zend_hash_reverse_apply(EG(class_table), (apply_func_t) is_not_internal_class TSRMLS_CC); } zend_end_try(); /* The regular list must be destroyed after the main symbol table and diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 5ccebd8faf..12fbfd35dc 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -723,6 +723,33 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t de } +ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) +{ + Bucket *p, *q; + + IS_CONSISTENT(ht); + + HASH_PROTECT_RECURSION(ht); + p = ht->pListTail; + while (p != NULL) { + int result = apply_func(p->pData TSRMLS_CC); + + q = p; + p = p->pListLast; + if (result & ZEND_HASH_APPLY_REMOVE) { + if (q->nKeyLength>0) { + zend_hash_del(ht, q->arKey, q->nKeyLength); + } else { + zend_hash_index_del(ht, q->h); + } + } + if (result & ZEND_HASH_APPLY_STOP) { + break; + } + } + HASH_UNPROTECT_RECURSION(ht); +} + ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 72eecb4748..76010776ad 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -102,6 +102,11 @@ ZEND_API int zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLength); + +#define ZEND_HASH_APPLY_KEEP 0 +#define ZEND_HASH_APPLY_REMOVE 1<<0 +#define ZEND_HASH_APPLY_STOP 1<<1 + typedef struct _zend_hash_key { char *arKey; uint nKeyLength; @@ -118,7 +123,13 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC); ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void * TSRMLS_DC); ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int, ...); - +/* This function should be used with special care (in other words, + * it should usually not be used). When used with the ZEND_HASH_APPLY_STOP + * return value, it assumes things about the order of the elements in the hash. + * Also, it does not provide the same kind of reentrancy protection that + * the standard apply functions do. + */ +ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC); /* Deletes */