]> granicus.if.org Git - php/commitdiff
Avoid going over huge lists of functions, classes and constants.
authorZeev Suraski <zeev@php.net>
Thu, 2 Aug 2001 07:00:43 +0000 (07:00 +0000)
committerZeev Suraski <zeev@php.net>
Thu, 2 Aug 2001 07:00:43 +0000 (07:00 +0000)
Special thanks to the guys from the MS lab for the profiling tools :)

Zend/zend_constants.c
Zend/zend_execute_API.c
Zend/zend_hash.c
Zend/zend_hash.h

index cb4ac03333727e0617e07db2914065df620da484..d76619ccbf31d82e4ce7aa8202d4088389ff693d 100644 (file)
@@ -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);
 }
 
 
index 6ee4fd963495877117568ce642a7574baba58c11..1c9e42a5e41699166694468e9d031128fa82e586 100644 (file)
@@ -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
index 5ccebd8faf35236efc2cc1b6f1e6179a6f809672..12fbfd35dc0edf0d6a1d05cfaa62eba5f8a8d929 100644 (file)
@@ -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)
 {
index 72eecb47486ff12a78076e1996fe26bf8b5d932a..76010776adbc8db939bdeea21462e4d37a7e7288 100644 (file)
@@ -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 */