Skip to content
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

ext/pcre: Refactor preg_replace_callback(_array)() to not pass a useless FCI #17365

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

Girgias
Copy link
Member

@Girgias Girgias commented Jan 5, 2025

And other drive-by refactorings.

This fixes an unclean shutdown with trampolines for preg_replace_callback_array(), I just don't know what causes it atm.

…able*

This makes the assumption the zval is always an array explicit
We don't need the FCI anymore, and we always have the subject as a zend_string.
We don't need the FCI anymore
We don't need the FCI anymore
Make the Hashtable param const
Throw exception on non string entries
We don't need the FCI anymore
Make the Hashtable params const
Rename function to indicate it is a PHP pcre function
@Girgias Girgias force-pushed the pcre-fci-refactor branch from 4d66c68 to 64f7aa1 Compare January 5, 2025 13:32
@Girgias Girgias force-pushed the pcre-fci-refactor branch from 64f7aa1 to 10435d2 Compare January 5, 2025 13:35
@Girgias Girgias marked this pull request as ready for review January 5, 2025 13:59
Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this PR is fine (and does more welcome cleanup than just the FCI stuff).

What I'm just not entirely convinced by is if in this particular case getting rid of FCI passing is a good idea. If we don't pass it, the engine makes an FCI itself and also needs to do a bit extra work when dealing with trampolines:

php-src/Zend/zend_API.h

Lines 847 to 851 in 47f1cae

if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
func = (zend_function*) emalloc(sizeof(zend_function));
memcpy(func, fcc->function_handler, sizeof(zend_function));
zend_string_addref(func->op_array.function_name);
}

But we already have an FCI anyway (that we don't store), so I'm not sure how much improvement this actually is.

pcre2_get_mark(match_data), flags);

ZEND_ASSERT(eval_result);
if (UNEXPECTED(eval_result == NULL)) {
goto error;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure this is right. This error path calls into pcre_handle_exec_error(count) where count represents an error code normally. However, in this call this is a real count and not an error code.
I was first thinking that you should probably set PCRE_G(error_code) yourself. However, perhaps not even that is necessary because we're throwing a userland exception anyway (which is not a pcre error itself).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I wasn't exactly sure myself here.

ext/pcre/tests/preg_replace_callback_array_trampoline.phpt Outdated Show resolved Hide resolved
@Girgias
Copy link
Member Author

Girgias commented Jan 6, 2025

Most of this PR is fine (and does more welcome cleanup than just the FCI stuff).

What I'm just not entirely convinced by is if in this particular case getting rid of FCI passing is a good idea. If we don't pass it, the engine makes an FCI itself and also needs to do a bit extra work when dealing with trampolines:

php-src/Zend/zend_API.h

Lines 847 to 851 in 47f1cae

if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
func = (zend_function*) emalloc(sizeof(zend_function));
memcpy(func, fcc->function_handler, sizeof(zend_function));
zend_string_addref(func->op_array.function_name);
}

But we already have an FCI anyway (that we don't store), so I'm not sure how much improvement this actually is.

Long term, I am trying to see if I can get rid of the function_name zval in the FCI struct and only rely on the FCC for the actual function, trampolines are slightly annoying in this regard. I don't know enough about hardware to know if reducing argument count is helpful or not, but most of the FCI initialization is done just prior to calling it anyway here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants