Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ad844a4
update register
withinboredom Aug 17, 2024
8771a49
get registration working
withinboredom Aug 17, 2024
a904ab1
add autoloading to function_exists
withinboredom Aug 17, 2024
d7e1972
add more functions
withinboredom Aug 17, 2024
018cb5b
fix trivial test issues
withinboredom Aug 17, 2024
54bb71d
fix default parameter for spl_autoload_call
withinboredom Aug 17, 2024
881f7bb
add some tests and fix a typo
withinboredom Aug 17, 2024
8af4c9e
ensure no output from handler
withinboredom Aug 17, 2024
76d831d
update spl_autoload
withinboredom Aug 18, 2024
185bcf8
perform a better check
withinboredom Aug 18, 2024
e53ea12
update and add tests showing spl_autoload failure
withinboredom Aug 18, 2024
3df2142
update original opcode handlers
withinboredom Aug 18, 2024
c40da04
handle dynamic functions
withinboredom Aug 18, 2024
6937ac6
clone a test repo to get benchmarks
withinboredom Aug 18, 2024
2cf112d
ensure casing is not lower-cased
withinboredom Aug 18, 2024
d344f4a
ensure single autoloading
withinboredom Aug 18, 2024
4d65482
clean up is_callable check a bit
withinboredom Aug 18, 2024
716ade8
fix typo
withinboredom Aug 18, 2024
937dab8
add one more test here
withinboredom Aug 18, 2024
87b37e8
allow getting autoloaders for both classes and functions
withinboredom Aug 18, 2024
4ec1efd
show error conditions
withinboredom Aug 18, 2024
1736697
specify that it is optional
withinboredom Aug 18, 2024
02a9e9c
add another test
withinboredom Aug 19, 2024
1aab759
remove second parameter from callbacks
withinboredom Sep 3, 2024
7dcab2e
ensure we only autoload once if not found
withinboredom Sep 3, 2024
b88b1d5
optimization to allow known hashes to be faster
withinboredom Sep 3, 2024
bc9c492
handle specifying multiple types
withinboredom Sep 3, 2024
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: 4 additions & 4 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -3861,22 +3861,22 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_
if (!ce_org) {
zend_function *func;
zend_string *lmname;
zend_string *name = Z_STR_P(callable);

/* Check if function with given name exists.
* This may be a compound name that includes namespace name */
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
/* Skip leading \ */
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
func = zend_fetch_function(lmname);
func = zend_fetch_function(name, lmname);
ZSTR_ALLOCA_FREE(lmname, use_heap);
} else {
lmname = Z_STR_P(callable);
func = zend_fetch_function(lmname);
func = zend_fetch_function(name, name);
if (!func) {
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
func = zend_fetch_function(lmname);
func = zend_fetch_function(name, lmname);
ZSTR_ALLOCA_FREE(lmname, use_heap);
}
}
Expand Down
11 changes: 9 additions & 2 deletions Zend/zend_builtin_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,10 +1162,13 @@ ZEND_FUNCTION(function_exists)
{
zend_string *name;
bool exists;
bool autoload = 1;
zend_string *lcname;

ZEND_PARSE_PARAMETERS_START(1, 1)
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(name)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(autoload)
ZEND_PARSE_PARAMETERS_END();

if (ZSTR_VAL(name)[0] == '\\') {
Expand All @@ -1176,7 +1179,11 @@ ZEND_FUNCTION(function_exists)
lcname = zend_string_tolower(name);
}

exists = zend_hash_exists(EG(function_table), lcname);
if (autoload) {
exists = zend_locate_function(name, lcname);
} else {
exists = zend_hash_exists(EG(function_table), lcname);
}
zend_string_release_ex(lcname, 0);

RETURN_BOOL(exists);
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_builtin_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function trait_exists(string $trait, bool $autoload = true): bool {}

function enum_exists(string $enum, bool $autoload = true): bool {}

function function_exists(string $function): bool {}
function function_exists(string $function, bool $autoload = true): bool {}

function class_alias(string $class, string $alias, bool $autoload = true): bool {}

Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_builtin_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 25 additions & 3 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -4250,9 +4250,9 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
}
/* }}} */

ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name, zend_string *lc_name) /* {{{ */
{
zval *zv = zend_hash_find(EG(function_table), name);
zval *zv = zend_locate_function(name, lc_name);

if (EXPECTED(zv != NULL)) {
zend_function *fbc = Z_FUNC_P(zv);
Expand Down Expand Up @@ -4859,6 +4859,28 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
/* }}} */
#endif

zval* zend_locate_function(zend_string *function_name, zend_string *lc_name) /* {{{ */
{
zval *func;
func = zend_hash_find(EG(function_table), lc_name);
if (func == NULL && zend_autoload_function) {
zend_string *previous_filename = EG(filename_override);
zend_long previous_lineno = EG(lineno_override);
EG(filename_override) = NULL;
EG(lineno_override) = -1;
zend_exception_save();

func = zend_autoload_function(function_name, lc_name);

zend_exception_restore();
EG(filename_override) = previous_filename;
EG(lineno_override) = previous_lineno;
}

return func;
}
/* }}} */

static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
{
zend_function *fbc;
Expand Down Expand Up @@ -4920,7 +4942,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
} else {
lcname = zend_string_tolower(function);
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
if (UNEXPECTED((func = zend_locate_function(function, lcname)) == NULL)) {
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
zend_string_release_ex(lcname, 0);
return NULL;
Expand Down
4 changes: 3 additions & 1 deletion Zend/zend_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, z

/* The lc_name may be stack allocated! */
ZEND_API extern zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name);
ZEND_API extern zval *(*zend_autoload_function)(zend_string *name, zend_string *lc_name);

void init_executor(void);
void shutdown_executor(void);
Expand All @@ -50,6 +51,7 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val
ZEND_API bool zend_is_valid_class_name(zend_string *name);
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags);
ZEND_API zval *zend_locate_function(zend_string *function_name, zend_string *lcname);
ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);
ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex);
ZEND_API zend_result zend_eval_string(const char *str, zval *retval_ptr, const char *string_name);
Expand Down Expand Up @@ -405,7 +407,7 @@ ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fe
ZEND_API zend_class_entry *zend_fetch_class_with_scope(zend_string *class_name, uint32_t fetch_type, zend_class_entry *scope);
ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, uint32_t fetch_type);

ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name);
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name, zend_string *lc_name);
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len);
ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array);

Expand Down
1 change: 1 addition & 0 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name);
ZEND_API zval *(*zend_autoload_function)(zend_string *name, zend_string *lc_name);

/* true globals */
ZEND_API const zend_fcall_info empty_fcall_info = {0};
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -3834,7 +3834,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
fbc = CACHED_PTR(opline->result.num);
if (UNEXPECTED(fbc == NULL)) {
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
func = zend_locate_function(Z_STR_P(function_name), Z_STR_P(function_name+1));
if (UNEXPECTED(func == NULL)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
}
Expand Down Expand Up @@ -3978,7 +3978,7 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
fbc = CACHED_PTR(opline->result.num);
if (UNEXPECTED(fbc == NULL)) {
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
func = zend_locate_function(Z_STR_P(func_name + 1), Z_STR_P(func_name + 1));
if (func == NULL) {
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
if (UNEXPECTED(func == NULL)) {
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion benchmark/benchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function runBench(bool $jit): array {

function runSymfonyDemo(bool $jit): array {
$dir = __DIR__ . '/repos/symfony-demo-2.2.3';
cloneRepo($dir, 'https://github.com/php/benchmarking-symfony-demo-2.2.3.git');
cloneRepo($dir, 'https://github.com/withinboredom/benchmarking-symfony-demo-2.2.3.git');
runPhpCommand([$dir . '/bin/console', 'cache:clear']);
runPhpCommand([$dir . '/bin/console', 'cache:warmup']);
return runValgrindPhpCgiCommand('symfony-demo', [$dir . '/public/index.php'], cwd: $dir, jit: $jit, warmup: 50, repeat: 50);
Expand Down
4 changes: 2 additions & 2 deletions ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,11 +1643,11 @@ ZEND_METHOD(ReflectionFunction, __construct)
ALLOCA_FLAG(use_heap)
ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
fptr = zend_fetch_function(lcname);
fptr = zend_fetch_function(fname, lcname);
ZSTR_ALLOCA_FREE(lcname, use_heap);
} else {
lcname = zend_string_tolower(fname);
fptr = zend_fetch_function(lcname);
fptr = zend_fetch_function(fname, lcname);
zend_string_release(lcname);
}

Expand Down
Loading