Skip to content

Commit 81e9c0c

Browse files
committed
Introduce zend_lookup_function()
1 parent 53c6619 commit 81e9c0c

File tree

6 files changed

+92
-75
lines changed

6 files changed

+92
-75
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
@@ -3882,19 +3882,19 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
38823882

38833883
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
38843884
{
3885-
zval *zv = zend_hash_find(EG(function_table), name);
3885+
zend_function *fbc = zend_lookup_function(name);
38863886

3887-
if (EXPECTED(zv != NULL)) {
3888-
zend_function *fbc = Z_FUNC_P(zv);
3887+
if (UNEXPECTED(fbc == NULL)) {
3888+
return NULL;
3889+
}
38893890

3890-
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3891-
init_func_run_time_cache_i(&fbc->op_array);
3892-
}
3893-
return fbc;
3891+
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3892+
init_func_run_time_cache_i(&fbc->op_array);
38943893
}
3895-
return NULL;
3894+
return fbc;
38963895
} /* }}} */
38973896

3897+
// TODO Update or drop as this indicates a zend_call_method() without an object...
38983898
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
38993899
{
39003900
zval *zv = zend_hash_str_find(EG(function_table), name, len);
@@ -4262,7 +4262,6 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
42624262
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
42634263
{
42644264
zend_function *fbc;
4265-
zval *func;
42664265
zend_class_entry *called_scope;
42674266
zend_string *lcname;
42684267
const char *colon;
@@ -4314,20 +4313,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
43144313
init_func_run_time_cache(&fbc->op_array);
43154314
}
43164315
} else {
4317-
if (ZSTR_VAL(function)[0] == '\\') {
4318-
lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4319-
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
4320-
} else {
4321-
lcname = zend_string_tolower(function);
4322-
}
4323-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4316+
if (UNEXPECTED((fbc = zend_lookup_function(function)) == NULL)) {
43244317
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4325-
zend_string_release_ex(lcname, 0);
43264318
return NULL;
43274319
}
4328-
zend_string_release_ex(lcname, 0);
43294320

4330-
fbc = Z_FUNC_P(func);
43314321
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
43324322
init_func_run_time_cache(&fbc->op_array);
43334323
}

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
@@ -1065,6 +1065,64 @@ static const uint32_t valid_chars[8] = {
10651065
0xffffffff,
10661066
};
10671067

1068+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lc_key, bool use_autoload)
1069+
{
1070+
zend_function *fbc = NULL;
1071+
zval *func;
1072+
zend_string *lc_name;
1073+
zend_string *autoload_name;
1074+
1075+
if (lc_key) {
1076+
lc_name = lc_key;
1077+
} else {
1078+
if (name == NULL || !ZSTR_LEN(name)) {
1079+
return NULL;
1080+
}
1081+
1082+
if (ZSTR_VAL(name)[0] == '\\') {
1083+
lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1084+
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1085+
} else {
1086+
lc_name = zend_string_tolower(name);
1087+
}
1088+
}
1089+
1090+
func = zend_hash_find(EG(function_table), lc_name);
1091+
1092+
if (EXPECTED(func)) {
1093+
if (!lc_key) {
1094+
zend_string_release_ex(lc_name, 0);
1095+
}
1096+
fbc = Z_FUNC_P(func);
1097+
return fbc;
1098+
}
1099+
1100+
/* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1101+
if (!use_autoload || zend_is_compiling()) {
1102+
if (!lc_key) {
1103+
zend_string_release_ex(lc_name, 0);
1104+
}
1105+
return NULL;
1106+
}
1107+
1108+
if (!zend_autoload) {
1109+
if (!lc_key) {
1110+
zend_string_release_ex(lc_name, 0);
1111+
}
1112+
return NULL;
1113+
}
1114+
1115+
if (!lc_key) {
1116+
zend_string_release_ex(lc_name, 0);
1117+
}
1118+
return NULL;
1119+
}
1120+
1121+
ZEND_API zend_function *zend_lookup_function(zend_string *name) /* {{{ */
1122+
{
1123+
return zend_lookup_function_ex(name, NULL, 0);
1124+
}
1125+
10681126
ZEND_API bool zend_is_valid_class_name(zend_string *name) {
10691127
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
10701128
unsigned char c = ZSTR_VAL(name)[i];

Zend/zend_vm_def.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3696,17 +3696,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
36963696
{
36973697
USE_OPLINE
36983698
zend_function *fbc;
3699-
zval *function_name, *func;
37003699
zend_execute_data *call;
37013700

37023701
fbc = CACHED_PTR(opline->result.num);
37033702
if (UNEXPECTED(fbc == NULL)) {
3704-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3705-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3706-
if (UNEXPECTED(func == NULL)) {
3703+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3704+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3705+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3706+
if (UNEXPECTED(fbc == NULL)) {
37073707
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
37083708
}
3709-
fbc = Z_FUNC_P(func);
37103709
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
37113710
init_func_run_time_cache(&fbc->op_array);
37123711
}
@@ -3838,22 +3837,19 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
38383837
ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38393838
{
38403839
USE_OPLINE
3841-
zval *func_name;
3842-
zval *func;
38433840
zend_function *fbc;
38443841
zend_execute_data *call;
38453842

38463843
fbc = CACHED_PTR(opline->result.num);
38473844
if (UNEXPECTED(fbc == NULL)) {
3848-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3849-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3850-
if (func == NULL) {
3851-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3852-
if (UNEXPECTED(func == NULL)) {
3845+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3846+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3847+
if (fbc == NULL) {
3848+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3849+
if (fbc == NULL) {
38533850
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
38543851
}
38553852
}
3856-
fbc = Z_FUNC_P(func);
38573853
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
38583854
init_func_run_time_cache(&fbc->op_array);
38593855
}
@@ -3871,15 +3867,13 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38713867
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
38723868
{
38733869
USE_OPLINE
3874-
zval *fname;
3875-
zval *func;
38763870
zend_function *fbc;
38773871
zend_execute_data *call;
38783872

38793873
fbc = CACHED_PTR(opline->result.num);
38803874
if (UNEXPECTED(fbc == NULL)) {
3881-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3882-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3875+
zval *fname = (zval*)RT_CONSTANT(opline, opline->op2);
3876+
zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
38833877
ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
38843878
fbc = Z_FUNC_P(func);
38853879
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {

Zend/zend_vm_execute.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,17 +3565,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME
35653565
{
35663566
USE_OPLINE
35673567
zend_function *fbc;
3568-
zval *function_name, *func;
35693568
zend_execute_data *call;
35703569

35713570
fbc = CACHED_PTR(opline->result.num);
35723571
if (UNEXPECTED(fbc == NULL)) {
3573-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3574-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3575-
if (UNEXPECTED(func == NULL)) {
3572+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3573+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3574+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3575+
if (UNEXPECTED(fbc == NULL)) {
35763576
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
35773577
}
3578-
fbc = Z_FUNC_P(func);
35793578
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
35803579
init_func_run_time_cache(&fbc->op_array);
35813580
}
@@ -3645,22 +3644,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_H
36453644
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
36463645
{
36473646
USE_OPLINE
3648-
zval *func_name;
3649-
zval *func;
36503647
zend_function *fbc;
36513648
zend_execute_data *call;
36523649

36533650
fbc = CACHED_PTR(opline->result.num);
36543651
if (UNEXPECTED(fbc == NULL)) {
3655-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3656-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3657-
if (func == NULL) {
3658-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3659-
if (UNEXPECTED(func == NULL)) {
3652+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3653+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3654+
if (fbc == NULL) {
3655+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3656+
if (fbc == NULL) {
36603657
ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
36613658
}
36623659
}
3663-
fbc = Z_FUNC_P(func);
36643660
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
36653661
init_func_run_time_cache(&fbc->op_array);
36663662
}
@@ -3678,15 +3674,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N
36783674
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
36793675
{
36803676
USE_OPLINE
3681-
zval *fname;
3682-
zval *func;
36833677
zend_function *fbc;
36843678
zend_execute_data *call;
36853679

36863680
fbc = CACHED_PTR(opline->result.num);
36873681
if (UNEXPECTED(fbc == NULL)) {
3688-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3689-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3682+
zval *fname = (zval*)RT_CONSTANT(opline, opline->op2);
3683+
zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
36903684
ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
36913685
fbc = Z_FUNC_P(func);
36923686
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {

0 commit comments

Comments
 (0)