Skip to content

Refactor FCI API #9723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ PHP 8.4 INTERNALS UPGRADE NOTES
1. Internal API changes
========================

* The following FCI APIs have been removed as they were confusing:
- zend_fcall_info_call()
- zend_fcall_info_args_save()
- zend_fcall_info_args_restore()
- zend_fcall_info_argn()
- zend_fcall_info_argv()
- zend_fcall_info_argp()

========================
2. Build system changes
========================
Expand Down
82 changes: 0 additions & 82 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -4136,23 +4136,6 @@ ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem) /*
}
/* }}} */

ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params) /* {{{ */
{
*param_count = fci->param_count;
*params = fci->params;
fci->param_count = 0;
fci->params = NULL;
}
/* }}} */

ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */
{
zend_fcall_info_args_clear(fci, 1);
fci->param_count = param_count;
fci->params = params;
}
/* }}} */

ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
{
zval *arg, *params;
Expand Down Expand Up @@ -4192,71 +4175,6 @@ ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {
}
/* }}} */

ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv) /* {{{ */
{
zend_fcall_info_args_clear(fci, !argc);

if (argc) {
fci->param_count = argc;
fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));

for (uint32_t i = 0; i < argc; ++i) {
ZVAL_COPY(&fci->params[i], &argv[i]);
}
}
}
/* }}} */

ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv) /* {{{ */
{
zend_fcall_info_args_clear(fci, !argc);

if (argc) {
zval *arg;
fci->param_count = argc;
fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));

for (uint32_t i = 0; i < argc; ++i) {
arg = va_arg(*argv, zval *);
ZVAL_COPY(&fci->params[i], arg);
}
}
}
/* }}} */

ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...) /* {{{ */
{
va_list argv;

va_start(argv, argc);
zend_fcall_info_argv(fci, argc, &argv);
va_end(argv);
}
/* }}} */

ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
{
zval retval, *org_params = NULL;
uint32_t org_count = 0;
zend_result result;

fci->retval = retval_ptr ? retval_ptr : &retval;
if (args) {
zend_fcall_info_args_save(fci, &org_count, &org_params);
zend_fcall_info_args(fci, args);
}
result = zend_call_function(fci, fcc);

if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
zval_ptr_dtor(&retval);
}
if (args) {
zend_fcall_info_args_restore(fci, org_count, org_params);
}
return result;
}
/* }}} */

ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, zval *callable)
{
if (fcc->closure) {
Expand Down
32 changes: 0 additions & 32 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,44 +701,12 @@ ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags,
*/
ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem);

/** Save current arguments from zend_fcall_info *fci
* params array will be set to NULL
*/
ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params);

/** Free arguments connected with zend_fcall_info *fci and set back saved ones.
*/
ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params);

/** Set or clear the arguments in the zend_call_info struct taking care of
* refcount. If args is NULL and arguments are set then those are cleared.
*/
ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args);
ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args);

/** Set arguments in the zend_fcall_info struct taking care of refcount.
* If argc is 0 the arguments which are set will be cleared, else pass
* a variable amount of zval** arguments.
*/
ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv);

/** Set arguments in the zend_fcall_info struct taking care of refcount.
* If argc is 0 the arguments which are set will be cleared, else pass
* a variable amount of zval** arguments.
*/
ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv);

/** Set arguments in the zend_fcall_info struct taking care of refcount.
* If argc is 0 the arguments which are set will be cleared, else pass
* a variable amount of zval** arguments.
*/
ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...);

/** Call a function using information created by zend_fcall_info_init()/args().
* If args is given then those replace the argument info in fci is temporarily.
*/
ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval, zval *args);

/* Zend FCC API to store and handle PHP userland functions */
static zend_always_inline bool zend_fcc_equals(const zend_fcall_info_cache* a, const zend_fcall_info_cache* b)
{
Expand Down
43 changes: 24 additions & 19 deletions ext/standard/basic_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,36 +1594,45 @@ PHP_FUNCTION(forward_static_call_array)
}
/* }}} */

static void fci_addref(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
static void php_user_callable_addref_with_params(zend_fcall_info *fci, zend_fcall_info_cache *fcc, const zval *params)
{
Z_TRY_ADDREF(fci->function_name);
if (fci_cache->object) {
GC_ADDREF(fci_cache->object);
fci->params = NULL;
if (params) {
ZEND_ASSERT(fci->param_count > 0);
fci->params = (zval *) safe_erealloc(fci->params, sizeof(zval), fci->param_count, 0);
for (uint32_t i = 0; i < fci->param_count; ++i) {
ZVAL_COPY(&fci->params[i], &params[i]);
}
}
zend_fcc_addref(fcc);
}

static void fci_release(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
static void php_user_callable_dtor_with_params(zend_fcall_info *fci, zend_fcall_info_cache *fcc)
{
zval_ptr_dtor(&fci->function_name);
if (fci_cache->object) {
zend_object_release(fci_cache->object);
if (fci->params) {
ZEND_ASSERT(fci->param_count > 0);
for (uint32_t i = 0; i < fci->param_count; ++i) {
zval_ptr_dtor(&fci->params[i]);
}
efree(fci->params);
}
zend_fcc_dtor(fcc);
}

void user_shutdown_function_dtor(zval *zv) /* {{{ */
{
php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);

zend_fcall_info_args_clear(&shutdown_function_entry->fci, true);
fci_release(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
php_user_callable_dtor_with_params(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
efree(shutdown_function_entry);
}
/* }}} */

void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
{
zend_fcall_info_args_clear(&tick_function_entry->fci, true);
fci_release(&tick_function_entry->fci, &tick_function_entry->fci_cache);
php_user_callable_dtor_with_params(&tick_function_entry->fci, &tick_function_entry->fci_cache);
}
/* }}} */

Expand Down Expand Up @@ -1721,16 +1730,14 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */
PHP_FUNCTION(register_shutdown_function)
{
php_shutdown_function_entry entry;
zval *params = NULL;
uint32_t param_count = 0;
bool status;
zval *params = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &entry.fci, &entry.fci_cache, &params, &param_count) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &entry.fci, &entry.fci_cache, &params, &entry.fci.param_count) == FAILURE) {
RETURN_THROWS();
}

fci_addref(&entry.fci, &entry.fci_cache);
zend_fcall_info_argp(&entry.fci, param_count, params);
php_user_callable_addref_with_params(&entry.fci, &entry.fci_cache, params);

status = append_user_shutdown_function(&entry);
ZEND_ASSERT(status);
Expand Down Expand Up @@ -2310,15 +2317,13 @@ PHP_FUNCTION(register_tick_function)
{
user_tick_function_entry tick_fe;
zval *params = NULL;
uint32_t param_count = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &tick_fe.fci, &tick_fe.fci_cache, &params, &param_count) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &tick_fe.fci, &tick_fe.fci_cache, &params, &tick_fe.fci.param_count) == FAILURE) {
RETURN_THROWS();
}

tick_fe.calling = false;
fci_addref(&tick_fe.fci, &tick_fe.fci_cache);
zend_fcall_info_argp(&tick_fe.fci, param_count, params);
php_user_callable_addref_with_params(&tick_fe.fci, &tick_fe.fci_cache, params);

if (!BG(user_tick_functions)) {
BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
Expand Down