* allocated block separately, but we like to call all the destructors and
* callbacks in exactly the same order.
*/
+static void accel_fast_zval_dtor(zval *zvalue);
static void accel_fast_hash_destroy(HashTable *ht)
{
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
- ht->pDestructor(&p->val);
+ accel_fast_zval_dtor(&p->val);
}
}
if (Z_ARR_P(zvalue) != &EG(symbol_table)) {
/* break possible cycles */
ZVAL_NULL(zvalue);
- Z_ARRVAL_P(zvalue)->pDestructor = accel_fast_zval_dtor;
accel_fast_hash_destroy(Z_ARRVAL_P(zvalue));
}
}
return ZEND_HASH_APPLY_STOP;
} else {
if (function->op_array.static_variables) {
- function->op_array.static_variables->pDestructor = accel_fast_zval_dtor;
accel_fast_hash_destroy(function->op_array.static_variables);
function->op_array.static_variables = NULL;
}
- return (--(*function->op_array.refcount) <= 0) ?
- ZEND_HASH_APPLY_REMOVE :
- ZEND_HASH_APPLY_KEEP;
- }
-}
-
-static int accel_cleanup_function_data(zval *zv TSRMLS_DC)
-{
- zend_function *function = Z_PTR_P(zv);
-
- if (function->type == ZEND_USER_FUNCTION) {
- if (function->op_array.static_variables) {
- function->op_array.static_variables->pDestructor = accel_fast_zval_dtor;
- accel_fast_hash_destroy(function->op_array.static_variables);
- function->op_array.static_variables = NULL;
- }
- }
- return 0;
-}
-
-static int accel_clean_non_persistent_class(zval *zv TSRMLS_DC)
-{
- zend_class_entry *ce = Z_PTR_P(zv);
-
- if (ce->type == ZEND_INTERNAL_CLASS) {
- return ZEND_HASH_APPLY_STOP;
- } else {
- if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
- zend_hash_apply(&ce->function_table, (apply_func_t) accel_cleanup_function_data TSRMLS_CC);
- }
- if (ce->static_members_table) {
- int i;
-
- for (i = 0; i < ce->default_static_members_count; i++) {
- accel_fast_zval_dtor(&ce->static_members_table[i]);
- ZVAL_UNDEF(&ce->static_members_table[i]);
- }
- ce->static_members_table = NULL;
- }
return ZEND_HASH_APPLY_REMOVE;
}
}
-static int accel_clean_non_persistent_constant(zval *zv TSRMLS_DC)
+static inline void zend_accel_fast_del_bucket(HashTable *ht, uint32_t idx, Bucket *p)
{
- zend_constant *c = Z_PTR_P(zv);
+ uint32_t nIndex = p->h & ht->nTableMask;
+ uint32_t i = ht->arHash[nIndex];
- if (c->flags & CONST_PERSISTENT) {
- return ZEND_HASH_APPLY_STOP;
- } else {
- return ZEND_HASH_APPLY_REMOVE;
+ ht->nNumUsed--;
+ ht->nNumOfElements--;
+ if (idx != i) {
+ Bucket *prev = ht->arData + i;
+ while (Z_NEXT(prev->val) != idx) {
+ i = Z_NEXT(prev->val);
+ prev = ht->arData + i;
+ }
+ Z_NEXT(prev->val) = Z_NEXT(p->val);
+ } else {
+ ht->arHash[p->h & ht->nTableMask] = Z_NEXT(p->val);
}
}
EG(symbol_table).ht.pDestructor = old_destructor;
}
zend_hash_init(&EG(symbol_table).ht, 8, NULL, NULL, 0);
- old_destructor = EG(function_table)->pDestructor;
- EG(function_table)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(function_table), (apply_func_t) accel_clean_non_persistent_function TSRMLS_CC);
- EG(function_table)->pDestructor = old_destructor;
- old_destructor = EG(class_table)->pDestructor;
- EG(class_table)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(class_table), (apply_func_t) accel_clean_non_persistent_class TSRMLS_CC);
- EG(class_table)->pDestructor = old_destructor;
- old_destructor = EG(zend_constants)->pDestructor;
- EG(zend_constants)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) accel_clean_non_persistent_constant TSRMLS_CC);
- EG(zend_constants)->pDestructor = old_destructor;
+
+ ZEND_HASH_REVERSE_FOREACH(EG(function_table), 0) {
+ zend_function *func = Z_PTR(_p->val);
+
+ if (func->type == ZEND_INTERNAL_FUNCTION) {
+ break;
+ } else {
+ if (func->op_array.static_variables) {
+ accel_fast_hash_destroy(func->op_array.static_variables);
+ }
+ zend_accel_fast_del_bucket(EG(function_table), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ ZEND_HASH_REVERSE_FOREACH(EG(class_table), 0) {
+ zend_class_entry *ce = Z_PTR(_p->val);
+
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ break;
+ } else {
+ if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
+ zend_function *func;
+
+ ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
+ if (func->type == ZEND_USER_FUNCTION) {
+ if (func->op_array.static_variables) {
+ accel_fast_hash_destroy(func->op_array.static_variables);
+ func->op_array.static_variables = NULL;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ if (ce->static_members_table) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ accel_fast_zval_dtor(&ce->static_members_table[i]);
+ ZVAL_UNDEF(&ce->static_members_table[i]);
+ }
+ ce->static_members_table = NULL;
+ }
+ zend_accel_fast_del_bucket(EG(class_table), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ ZEND_HASH_REVERSE_FOREACH(EG(zend_constants), 0) {
+ zend_constant *c = Z_PTR(_p->val);
+
+ if (c->flags & CONST_PERSISTENT) {
+ break;
+ } else {
+ zend_accel_fast_del_bucket(EG(zend_constants), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
}
CG(unclean_shutdown) = 1;
}