Skip to content

Commit 4208be5

Browse files
committed
Introduce zend_lookup_function()
1 parent c4d7cd5 commit 4208be5

File tree

6 files changed

+94
-79
lines changed

6 files changed

+94
-79
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,32 +3463,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_
34633463
int call_via_handler = 0;
34643464
zend_class_entry *scope;
34653465
zval *zv;
3466-
ALLOCA_FLAG(use_heap)
34673466

34683467
fcc->calling_scope = NULL;
34693468

34703469
if (!ce_org) {
3471-
zend_function *func;
3472-
zend_string *lmname;
3473-
3474-
/* Check if function with given name exists.
3475-
* This may be a compound name that includes namespace name */
3476-
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3477-
/* Skip leading \ */
3478-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3479-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3480-
func = zend_fetch_function(lmname);
3481-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3482-
} else {
3483-
lmname = Z_STR_P(callable);
3484-
func = zend_fetch_function(lmname);
3485-
if (!func) {
3486-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3487-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3488-
func = zend_fetch_function(lmname);
3489-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3490-
}
3491-
}
3470+
zend_function *func = zend_fetch_function(Z_STR_P(callable));
34923471
if (EXPECTED(func != NULL)) {
34933472
fcc->function_handler = func;
34943473
return 1;

Zend/zend_execute.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,19 +3774,19 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
37743774

37753775
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
37763776
{
3777-
zval *zv = zend_hash_find(EG(function_table), name);
3777+
zend_function *fbc = zend_lookup_function(name);
37783778

3779-
if (EXPECTED(zv != NULL)) {
3780-
zend_function *fbc = Z_FUNC_P(zv);
3779+
if (UNEXPECTED(fbc == NULL)) {
3780+
return NULL;
3781+
}
37813782

3782-
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3783-
init_func_run_time_cache_i(&fbc->op_array);
3784-
}
3785-
return fbc;
3783+
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3784+
init_func_run_time_cache_i(&fbc->op_array);
37863785
}
3787-
return NULL;
3786+
return fbc;
37883787
} /* }}} */
37893788

3789+
// TODO Update or drop as this indicates a zend_call_method() without an object...
37903790
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
37913791
{
37923792
zval *zv = zend_hash_str_find(EG(function_table), name, len);
@@ -4152,7 +4152,6 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
41524152
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
41534153
{
41544154
zend_function *fbc;
4155-
zval *func;
41564155
zend_class_entry *called_scope;
41574156
zend_string *lcname;
41584157
const char *colon;
@@ -4204,20 +4203,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
42044203
init_func_run_time_cache(&fbc->op_array);
42054204
}
42064205
} else {
4207-
if (ZSTR_VAL(function)[0] == '\\') {
4208-
lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4209-
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
4210-
} else {
4211-
lcname = zend_string_tolower(function);
4212-
}
4213-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4206+
if (UNEXPECTED((fbc = zend_lookup_function(function)) == NULL)) {
42144207
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4215-
zend_string_release_ex(lcname, 0);
42164208
return NULL;
42174209
}
4218-
zend_string_release_ex(lcname, 0);
42194210

4220-
fbc = Z_FUNC_P(func);
42214211
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
42224212
init_func_run_time_cache(&fbc->op_array);
42234213
}

Zend/zend_execute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value);
4646
ZEND_API void execute_ex(zend_execute_data *execute_data);
4747
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
4848
ZEND_API bool zend_is_valid_class_name(zend_string *name);
49+
ZEND_API zend_function *zend_lookup_function(zend_string *name);
50+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lcname, bool use_autoload);
4951
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
5052
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags);
5153
ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);

Zend/zend_execute_API.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,64 @@ static const uint32_t valid_chars[8] = {
10461046
0xffffffff,
10471047
};
10481048

1049+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lc_key, bool use_autoload)
1050+
{
1051+
zend_function *fbc = NULL;
1052+
zval *func;
1053+
zend_string *lc_name;
1054+
zend_string *autoload_name;
1055+
1056+
if (lc_key) {
1057+
lc_name = lc_key;
1058+
} else {
1059+
if (name == NULL || !ZSTR_LEN(name)) {
1060+
return NULL;
1061+
}
1062+
1063+
if (ZSTR_VAL(name)[0] == '\\') {
1064+
lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1065+
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1066+
} else {
1067+
lc_name = zend_string_tolower(name);
1068+
}
1069+
}
1070+
1071+
func = zend_hash_find(EG(function_table), lc_name);
1072+
1073+
if (EXPECTED(func)) {
1074+
if (!lc_key) {
1075+
zend_string_release_ex(lc_name, 0);
1076+
}
1077+
fbc = Z_FUNC_P(func);
1078+
return fbc;
1079+
}
1080+
1081+
/* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1082+
if (!use_autoload || zend_is_compiling()) {
1083+
if (!lc_key) {
1084+
zend_string_release_ex(lc_name, 0);
1085+
}
1086+
return NULL;
1087+
}
1088+
1089+
if (!zend_autoload) {
1090+
if (!lc_key) {
1091+
zend_string_release_ex(lc_name, 0);
1092+
}
1093+
return NULL;
1094+
}
1095+
1096+
if (!lc_key) {
1097+
zend_string_release_ex(lc_name, 0);
1098+
}
1099+
return NULL;
1100+
}
1101+
1102+
ZEND_API zend_function *zend_lookup_function(zend_string *name) /* {{{ */
1103+
{
1104+
return zend_lookup_function_ex(name, NULL, 0);
1105+
}
1106+
10491107
ZEND_API bool zend_is_valid_class_name(zend_string *name) {
10501108
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
10511109
unsigned char c = ZSTR_VAL(name)[i];

Zend/zend_vm_def.h

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3712,17 +3712,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
37123712
{
37133713
USE_OPLINE
37143714
zend_function *fbc;
3715-
zval *function_name, *func;
37163715
zend_execute_data *call;
37173716

37183717
fbc = CACHED_PTR(opline->result.num);
37193718
if (UNEXPECTED(fbc == NULL)) {
3720-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3721-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3722-
if (UNEXPECTED(func == NULL)) {
3719+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3720+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3721+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3722+
if (UNEXPECTED(fbc == NULL)) {
37233723
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
37243724
}
3725-
fbc = Z_FUNC_P(func);
37263725
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
37273726
init_func_run_time_cache(&fbc->op_array);
37283727
}
@@ -3854,22 +3853,19 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
38543853
ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38553854
{
38563855
USE_OPLINE
3857-
zval *func_name;
3858-
zval *func;
38593856
zend_function *fbc;
38603857
zend_execute_data *call;
38613858

38623859
fbc = CACHED_PTR(opline->result.num);
38633860
if (UNEXPECTED(fbc == NULL)) {
3864-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3865-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3866-
if (func == NULL) {
3867-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3868-
if (UNEXPECTED(func == NULL)) {
3861+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3862+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3863+
if (fbc == NULL) {
3864+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3865+
if (fbc == NULL) {
38693866
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
38703867
}
38713868
}
3872-
fbc = Z_FUNC_P(func);
38733869
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
38743870
init_func_run_time_cache(&fbc->op_array);
38753871
}
@@ -3887,19 +3883,16 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38873883
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
38883884
{
38893885
USE_OPLINE
3890-
zval *fname;
3891-
zval *func;
38923886
zend_function *fbc;
38933887
zend_execute_data *call;
38943888

38953889
fbc = CACHED_PTR(opline->result.num);
38963890
if (UNEXPECTED(fbc == NULL)) {
3897-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3898-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3899-
if (UNEXPECTED(func == NULL)) {
3891+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3892+
fbc = zend_lookup_function(Z_STR_P(function_name));
3893+
if (UNEXPECTED(fbc == NULL)) {
39003894
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
39013895
}
3902-
fbc = Z_FUNC_P(func);
39033896
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
39043897
init_func_run_time_cache(&fbc->op_array);
39053898
}

Zend/zend_vm_execute.h

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3550,17 +3550,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME
35503550
{
35513551
USE_OPLINE
35523552
zend_function *fbc;
3553-
zval *function_name, *func;
35543553
zend_execute_data *call;
35553554

35563555
fbc = CACHED_PTR(opline->result.num);
35573556
if (UNEXPECTED(fbc == NULL)) {
3558-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3559-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3560-
if (UNEXPECTED(func == NULL)) {
3557+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3558+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3559+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3560+
if (UNEXPECTED(fbc == NULL)) {
35613561
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
35623562
}
3563-
fbc = Z_FUNC_P(func);
35643563
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
35653564
init_func_run_time_cache(&fbc->op_array);
35663565
}
@@ -3630,22 +3629,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_H
36303629
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
36313630
{
36323631
USE_OPLINE
3633-
zval *func_name;
3634-
zval *func;
36353632
zend_function *fbc;
36363633
zend_execute_data *call;
36373634

36383635
fbc = CACHED_PTR(opline->result.num);
36393636
if (UNEXPECTED(fbc == NULL)) {
3640-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3641-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3642-
if (func == NULL) {
3643-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3644-
if (UNEXPECTED(func == NULL)) {
3637+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3638+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3639+
if (fbc == NULL) {
3640+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3641+
if (fbc == NULL) {
36453642
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
36463643
}
36473644
}
3648-
fbc = Z_FUNC_P(func);
36493645
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
36503646
init_func_run_time_cache(&fbc->op_array);
36513647
}
@@ -3663,19 +3659,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N
36633659
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
36643660
{
36653661
USE_OPLINE
3666-
zval *fname;
3667-
zval *func;
36683662
zend_function *fbc;
36693663
zend_execute_data *call;
36703664

36713665
fbc = CACHED_PTR(opline->result.num);
36723666
if (UNEXPECTED(fbc == NULL)) {
3673-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3674-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3675-
if (UNEXPECTED(func == NULL)) {
3667+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3668+
fbc = zend_lookup_function(Z_STR_P(function_name));
3669+
if (UNEXPECTED(fbc == NULL)) {
36763670
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
36773671
}
3678-
fbc = Z_FUNC_P(func);
36793672
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
36803673
init_func_run_time_cache(&fbc->op_array);
36813674
}

0 commit comments

Comments
 (0)