Skip to content

Commit 23387da

Browse files
committed
Introduce zend_lookup_function()
1 parent 8446b56 commit 23387da

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
@@ -3768,19 +3768,19 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
37683768

37693769
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
37703770
{
3771-
zval *zv = zend_hash_find(EG(function_table), name);
3771+
zend_function *fbc = zend_lookup_function(name);
37723772

3773-
if (EXPECTED(zv != NULL)) {
3774-
zend_function *fbc = Z_FUNC_P(zv);
3773+
if (UNEXPECTED(fbc == NULL)) {
3774+
return NULL;
3775+
}
37753776

3776-
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3777-
init_func_run_time_cache_i(&fbc->op_array);
3778-
}
3779-
return fbc;
3777+
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3778+
init_func_run_time_cache_i(&fbc->op_array);
37803779
}
3781-
return NULL;
3780+
return fbc;
37823781
} /* }}} */
37833782

3783+
// TODO Update or drop as this indicates a zend_call_method() without an object...
37843784
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
37853785
{
37863786
zval *zv = zend_hash_str_find(EG(function_table), name, len);
@@ -4146,7 +4146,6 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
41464146
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
41474147
{
41484148
zend_function *fbc;
4149-
zval *func;
41504149
zend_class_entry *called_scope;
41514150
zend_string *lcname;
41524151
const char *colon;
@@ -4198,20 +4197,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
41984197
init_func_run_time_cache(&fbc->op_array);
41994198
}
42004199
} else {
4201-
if (ZSTR_VAL(function)[0] == '\\') {
4202-
lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4203-
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
4204-
} else {
4205-
lcname = zend_string_tolower(function);
4206-
}
4207-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4200+
if (UNEXPECTED((fbc = zend_lookup_function(function)) == NULL)) {
42084201
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4209-
zend_string_release_ex(lcname, 0);
42104202
return NULL;
42114203
}
4212-
zend_string_release_ex(lcname, 0);
42134204

4214-
fbc = Z_FUNC_P(func);
42154205
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
42164206
init_func_run_time_cache(&fbc->op_array);
42174207
}

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
@@ -3684,17 +3684,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
36843684
{
36853685
USE_OPLINE
36863686
zend_function *fbc;
3687-
zval *function_name, *func;
36883687
zend_execute_data *call;
36893688

36903689
fbc = CACHED_PTR(opline->result.num);
36913690
if (UNEXPECTED(fbc == NULL)) {
3692-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3693-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3694-
if (UNEXPECTED(func == NULL)) {
3691+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3692+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3693+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3694+
if (UNEXPECTED(fbc == NULL)) {
36953695
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
36963696
}
3697-
fbc = Z_FUNC_P(func);
36983697
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
36993698
init_func_run_time_cache(&fbc->op_array);
37003699
}
@@ -3826,22 +3825,19 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
38263825
ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38273826
{
38283827
USE_OPLINE
3829-
zval *func_name;
3830-
zval *func;
38313828
zend_function *fbc;
38323829
zend_execute_data *call;
38333830

38343831
fbc = CACHED_PTR(opline->result.num);
38353832
if (UNEXPECTED(fbc == NULL)) {
3836-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3837-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3838-
if (func == NULL) {
3839-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3840-
if (UNEXPECTED(func == NULL)) {
3833+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3834+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3835+
if (fbc == NULL) {
3836+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3837+
if (fbc == NULL) {
38413838
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
38423839
}
38433840
}
3844-
fbc = Z_FUNC_P(func);
38453841
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
38463842
init_func_run_time_cache(&fbc->op_array);
38473843
}
@@ -3859,19 +3855,16 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38593855
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
38603856
{
38613857
USE_OPLINE
3862-
zval *fname;
3863-
zval *func;
38643858
zend_function *fbc;
38653859
zend_execute_data *call;
38663860

38673861
fbc = CACHED_PTR(opline->result.num);
38683862
if (UNEXPECTED(fbc == NULL)) {
3869-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3870-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3871-
if (UNEXPECTED(func == NULL)) {
3863+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3864+
fbc = zend_lookup_function(Z_STR_P(function_name));
3865+
if (UNEXPECTED(fbc == NULL)) {
38723866
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
38733867
}
3874-
fbc = Z_FUNC_P(func);
38753868
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
38763869
init_func_run_time_cache(&fbc->op_array);
38773870
}

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)