Don't use global for array_walk_fci

There's really no good reason for this to be a global, we can
easily pass it down to php_array_walk().
This commit is contained in:
Nikita Popov 2020-10-19 15:24:29 +02:00
parent d1845ac008
commit 9426c6e967
3 changed files with 24 additions and 49 deletions

View file

@ -1321,7 +1321,13 @@ PHP_FUNCTION(max)
} }
/* }}} */ /* }}} */
static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */ typedef struct {
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
} php_array_walk_context;
static int php_array_walk(
php_array_walk_context *context, zval *array, zval *userdata, int recursive)
{ {
zval args[3], /* Arguments to userland function */ zval args[3], /* Arguments to userland function */
retval, /* Return value - unused */ retval, /* Return value - unused */
@ -1331,15 +1337,19 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
uint32_t ht_iter; uint32_t ht_iter;
int result = SUCCESS; int result = SUCCESS;
/* Create a local copy of fci, as we want to use different arguments at different
* levels of recursion. */
zend_fcall_info fci = context->fci;
/* Set up known arguments */ /* Set up known arguments */
ZVAL_UNDEF(&args[1]); ZVAL_UNDEF(&args[1]);
if (userdata) { if (userdata) {
ZVAL_COPY(&args[2], userdata); ZVAL_COPY(&args[2], userdata);
} }
BG(array_walk_fci).retval = &retval; fci.retval = &retval;
BG(array_walk_fci).param_count = userdata ? 3 : 2; fci.param_count = userdata ? 3 : 2;
BG(array_walk_fci).params = args; fci.params = args;
zend_hash_internal_pointer_reset_ex(target_hash, &pos); zend_hash_internal_pointer_reset_ex(target_hash, &pos);
ht_iter = zend_hash_iterator_add(target_hash, pos); ht_iter = zend_hash_iterator_add(target_hash, pos);
@ -1386,8 +1396,6 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
if (recursive && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY) { if (recursive && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY) {
HashTable *thash; HashTable *thash;
zend_fcall_info orig_array_walk_fci;
zend_fcall_info_cache orig_array_walk_fci_cache;
zval ref; zval ref;
ZVAL_COPY_VALUE(&ref, zv); ZVAL_COPY_VALUE(&ref, zv);
@ -1400,28 +1408,20 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
break; break;
} }
/* backup the fcall info and cache */
orig_array_walk_fci = BG(array_walk_fci);
orig_array_walk_fci_cache = BG(array_walk_fci_cache);
Z_ADDREF(ref); Z_ADDREF(ref);
GC_PROTECT_RECURSION(thash); GC_PROTECT_RECURSION(thash);
result = php_array_walk(zv, userdata, recursive); result = php_array_walk(context, zv, userdata, recursive);
if (Z_TYPE_P(Z_REFVAL(ref)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL(ref))) { if (Z_TYPE_P(Z_REFVAL(ref)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL(ref))) {
/* If the hashtable changed in the meantime, we'll "leak" this apply count /* If the hashtable changed in the meantime, we'll "leak" this apply count
* increment -- our reference to thash is no longer valid. */ * increment -- our reference to thash is no longer valid. */
GC_UNPROTECT_RECURSION(thash); GC_UNPROTECT_RECURSION(thash);
} }
zval_ptr_dtor(&ref); zval_ptr_dtor(&ref);
/* restore the fcall info and cache */
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
} else { } else {
ZVAL_COPY(&args[0], zv); ZVAL_COPY(&args[0], zv);
/* Call the userland function */ /* Call the userland function */
result = zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache)); result = zend_call_function(&fci, &context->fci_cache);
if (result == SUCCESS) { if (result == SUCCESS) {
zval_ptr_dtor(&retval); zval_ptr_dtor(&retval);
} }
@ -1458,33 +1458,22 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
zend_hash_iterator_del(ht_iter); zend_hash_iterator_del(ht_iter);
return result; return result;
} }
/* }}} */
/* {{{ Apply a user function to every member of an array */ /* {{{ Apply a user function to every member of an array */
PHP_FUNCTION(array_walk) PHP_FUNCTION(array_walk)
{ {
zval *array; zval *array;
zval *userdata = NULL; zval *userdata = NULL;
zend_fcall_info orig_array_walk_fci; php_array_walk_context context;
zend_fcall_info_cache orig_array_walk_fci_cache;
orig_array_walk_fci = BG(array_walk_fci);
orig_array_walk_fci_cache = BG(array_walk_fci_cache);
ZEND_PARSE_PARAMETERS_START(2, 3) ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache)) Z_PARAM_FUNC(context.fci, context.fci_cache)
Z_PARAM_OPTIONAL Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(userdata) Z_PARAM_ZVAL(userdata)
ZEND_PARSE_PARAMETERS_END_EX( ZEND_PARSE_PARAMETERS_END();
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
return
);
php_array_walk(array, userdata, 0); php_array_walk(&context, array, userdata, 0);
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
RETURN_TRUE; RETURN_TRUE;
} }
/* }}} */ /* }}} */
@ -1494,26 +1483,16 @@ PHP_FUNCTION(array_walk_recursive)
{ {
zval *array; zval *array;
zval *userdata = NULL; zval *userdata = NULL;
zend_fcall_info orig_array_walk_fci; php_array_walk_context context;
zend_fcall_info_cache orig_array_walk_fci_cache;
orig_array_walk_fci = BG(array_walk_fci);
orig_array_walk_fci_cache = BG(array_walk_fci_cache);
ZEND_PARSE_PARAMETERS_START(2, 3) ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache)) Z_PARAM_FUNC(context.fci, context.fci_cache)
Z_PARAM_OPTIONAL Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(userdata) Z_PARAM_ZVAL(userdata)
ZEND_PARSE_PARAMETERS_END_EX( ZEND_PARSE_PARAMETERS_END();
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
return
);
php_array_walk(array, userdata, 1); php_array_walk(&context, array, userdata, 1);
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
RETURN_TRUE; RETURN_TRUE;
} }
/* }}} */ /* }}} */

View file

@ -463,8 +463,6 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
BG(strtok_last) = NULL; BG(strtok_last) = NULL;
BG(ctype_string) = NULL; BG(ctype_string) = NULL;
BG(locale_changed) = 0; BG(locale_changed) = 0;
BG(array_walk_fci) = empty_fcall_info;
BG(array_walk_fci_cache) = empty_fcall_info_cache;
BG(user_compare_fci) = empty_fcall_info; BG(user_compare_fci) = empty_fcall_info;
BG(user_compare_fci_cache) = empty_fcall_info_cache; BG(user_compare_fci_cache) = empty_fcall_info_cache;
BG(page_uid) = -1; BG(page_uid) = -1;

View file

@ -66,8 +66,6 @@ typedef struct _php_basic_globals {
char *strtok_last; char *strtok_last;
char strtok_table[256]; char strtok_table[256];
size_t strtok_len; size_t strtok_len;
zend_fcall_info array_walk_fci;
zend_fcall_info_cache array_walk_fci_cache;
zend_fcall_info user_compare_fci; zend_fcall_info user_compare_fci;
zend_fcall_info_cache user_compare_fci_cache; zend_fcall_info_cache user_compare_fci_cache;
zend_llist *user_tick_functions; zend_llist *user_tick_functions;