@@ -54,6 +54,18 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
54
54
return (zend_ast * ) ast ;
55
55
}
56
56
57
+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc (void ) {
58
+ zend_ast_fcc * ast ;
59
+
60
+ ast = zend_ast_alloc (sizeof (zend_ast_fcc ));
61
+ ast -> kind = ZEND_AST_CALLABLE_CONVERT ;
62
+ ast -> attr = 0 ;
63
+ ast -> lineno = ZEND_MAP_PTR_NEW_OFFSET ();
64
+ ZEND_MAP_PTR_NEW (ast -> fptr );
65
+
66
+ return (zend_ast * ) ast ;
67
+ }
68
+
57
69
static zend_always_inline zend_ast * zend_ast_create_zval_int (zval * zv , uint32_t attr , uint32_t lineno ) {
58
70
zend_ast_zval * ast ;
59
71
@@ -997,81 +1009,96 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
997
1009
switch (ast -> kind ) {
998
1010
case ZEND_AST_CALL : {
999
1011
ZEND_ASSERT (ast -> child [1 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1012
+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [1 ];
1013
+ fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
1000
1014
1001
- zend_string * function_name = zend_ast_get_str (ast -> child [0 ]);
1002
- zend_string * function_name_lc = zend_string_tolower (function_name );
1003
- fptr = zend_fetch_function (function_name_lc );
1004
- if (!fptr && ast -> child [0 ]-> attr != ZEND_NAME_FQ ) {
1005
- const char * backslash = zend_memrchr (ZSTR_VAL (function_name_lc ), '\\' , ZSTR_LEN (function_name_lc ));
1006
- if (backslash ) {
1007
- fptr = zend_fetch_function_str (backslash + 1 , ZSTR_LEN (function_name_lc ) - (backslash - ZSTR_VAL (function_name_lc ) + 1 ));
1008
- }
1009
- }
1010
- zend_string_release (function_name_lc );
1011
1015
if (!fptr ) {
1012
- zend_throw_error (NULL , "Call to undefined function %s()" , ZSTR_VAL (function_name ));
1013
- return FAILURE ;
1016
+ zend_string * function_name = zend_ast_get_str (ast -> child [0 ]);
1017
+ zend_string * function_name_lc = zend_string_tolower (function_name );
1018
+ fptr = zend_fetch_function (function_name_lc );
1019
+ if (!fptr && ast -> child [0 ]-> attr != ZEND_NAME_FQ ) {
1020
+ const char * backslash = zend_memrchr (ZSTR_VAL (function_name_lc ), '\\' , ZSTR_LEN (function_name_lc ));
1021
+ if (backslash ) {
1022
+ fptr = zend_fetch_function_str (backslash + 1 , ZSTR_LEN (function_name_lc ) - (backslash - ZSTR_VAL (function_name_lc ) + 1 ));
1023
+ }
1024
+ }
1025
+ zend_string_release (function_name_lc );
1026
+ if (!fptr ) {
1027
+ zend_throw_error (NULL , "Call to undefined function %s()" , ZSTR_VAL (function_name ));
1028
+ return FAILURE ;
1029
+ }
1030
+
1031
+ ZEND_MAP_PTR_SET (fcc_ast -> fptr , fptr );
1014
1032
}
1033
+
1015
1034
break ;
1016
1035
}
1017
1036
case ZEND_AST_STATIC_CALL : {
1018
1037
ZEND_ASSERT (ast -> child [2 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1038
+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [2 ];
1019
1039
1020
- zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
1021
- if (!ce ) {
1022
- return FAILURE ;
1023
- }
1024
- zend_string * method_name = zend_ast_get_str (ast -> child [1 ]);
1025
- if (ce -> get_static_method ) {
1026
- fptr = ce -> get_static_method (ce , method_name );
1027
- } else {
1028
- fptr = zend_hash_find_ptr_lc (& ce -> function_table , method_name );
1029
- if (fptr ) {
1030
- if (!(fptr -> common .fn_flags & ZEND_ACC_PUBLIC )) {
1031
- if (UNEXPECTED (fptr -> common .scope != scope )) {
1032
- if (
1033
- UNEXPECTED (fptr -> op_array .fn_flags & ZEND_ACC_PRIVATE )
1034
- || UNEXPECTED (!zend_check_protected (zend_get_function_root_class (fptr ), scope ))
1035
- ) {
1036
- if (ce -> __callstatic ) {
1037
- zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1038
- } else {
1039
- zend_bad_method_call (fptr , method_name , scope );
1040
- }
1040
+ fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
1041
1041
1042
- return FAILURE ;
1042
+ if (!fptr ) {
1043
+ zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
1044
+ if (!ce ) {
1045
+ return FAILURE ;
1046
+ }
1047
+ zend_string * method_name = zend_ast_get_str (ast -> child [1 ]);
1048
+ if (ce -> get_static_method ) {
1049
+ fptr = ce -> get_static_method (ce , method_name );
1050
+ } else {
1051
+ fptr = zend_hash_find_ptr_lc (& ce -> function_table , method_name );
1052
+ if (fptr ) {
1053
+ if (!(fptr -> common .fn_flags & ZEND_ACC_PUBLIC )) {
1054
+ if (UNEXPECTED (fptr -> common .scope != scope )) {
1055
+ if (
1056
+ UNEXPECTED (fptr -> op_array .fn_flags & ZEND_ACC_PRIVATE )
1057
+ || UNEXPECTED (!zend_check_protected (zend_get_function_root_class (fptr ), scope ))
1058
+ ) {
1059
+ if (ce -> __callstatic ) {
1060
+ zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1061
+ } else {
1062
+ zend_bad_method_call (fptr , method_name , scope );
1063
+ }
1064
+
1065
+ return FAILURE ;
1066
+ }
1043
1067
}
1044
1068
}
1045
- }
1046
- } else {
1047
- if (ce -> __callstatic ) {
1048
- zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1049
1069
} else {
1050
- zend_undefined_method (ce , method_name );
1070
+ if (ce -> __callstatic ) {
1071
+ zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1072
+ } else {
1073
+ zend_undefined_method (ce , method_name );
1074
+ }
1075
+
1076
+ return FAILURE ;
1051
1077
}
1078
+ }
1052
1079
1080
+ if (!(fptr -> common .fn_flags & ZEND_ACC_STATIC )) {
1081
+ zend_non_static_method_call (fptr );
1082
+
1053
1083
return FAILURE ;
1054
1084
}
1055
- }
1056
-
1057
- if (!(fptr -> common .fn_flags & ZEND_ACC_STATIC )) {
1058
- zend_non_static_method_call (fptr );
1059
-
1060
- return FAILURE ;
1061
- }
1062
- if ((fptr -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
1063
- zend_abstract_method_call (fptr );
1064
-
1065
- return FAILURE ;
1066
- } else if (fptr -> common .scope -> ce_flags & ZEND_ACC_TRAIT ) {
1067
- zend_error (E_DEPRECATED ,
1068
- "Calling static trait method %s::%s is deprecated, "
1069
- "it should only be called on a class using the trait" ,
1070
- ZSTR_VAL (fptr -> common .scope -> name ), ZSTR_VAL (fptr -> common .function_name ));
1071
- if (EG (exception )) {
1085
+ if ((fptr -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
1086
+ zend_abstract_method_call (fptr );
1087
+
1072
1088
return FAILURE ;
1089
+ } else if (fptr -> common .scope -> ce_flags & ZEND_ACC_TRAIT ) {
1090
+ zend_error (E_DEPRECATED ,
1091
+ "Calling static trait method %s::%s is deprecated, "
1092
+ "it should only be called on a class using the trait" ,
1093
+ ZSTR_VAL (fptr -> common .scope -> name ), ZSTR_VAL (fptr -> common .function_name ));
1094
+ if (EG (exception )) {
1095
+ return FAILURE ;
1096
+ }
1073
1097
}
1098
+
1099
+ ZEND_MAP_PTR_SET (fcc_ast -> fptr , fptr );
1074
1100
}
1101
+
1075
1102
break ;
1076
1103
}
1077
1104
}
@@ -1168,6 +1195,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
1168
1195
1169
1196
if (ast -> kind == ZEND_AST_ZVAL || ast -> kind == ZEND_AST_CONSTANT || ast -> kind == ZEND_AST_OP_ARRAY ) {
1170
1197
size = sizeof (zend_ast_zval );
1198
+ } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1199
+ size = sizeof (zend_ast_fcc );
1171
1200
} else if (zend_ast_is_list (ast )) {
1172
1201
uint32_t i ;
1173
1202
zend_ast_list * list = zend_ast_get_list (ast );
@@ -1231,6 +1260,13 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1231
1260
ZVAL_COPY (& new -> val , & ((zend_ast_zval * ) ast )-> val );
1232
1261
Z_LINENO (new -> val ) = zend_ast_get_lineno (ast );
1233
1262
buf = (void * )((char * )buf + sizeof (zend_ast_zval ));
1263
+ } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1264
+ zend_ast_fcc * new = (zend_ast_fcc * )buf ;
1265
+ new -> kind = ZEND_AST_CALLABLE_CONVERT ;
1266
+ new -> attr = ast -> attr ;
1267
+ new -> lineno = ast -> lineno ;
1268
+ new -> fptr__ptr = ((zend_ast_fcc * ) ast )-> fptr__ptr ;
1269
+ buf = (void * )((char * )buf + sizeof (zend_ast_fcc ));
1234
1270
} else {
1235
1271
uint32_t i , children = zend_ast_get_num_children (ast );
1236
1272
zend_ast * new = (zend_ast * )buf ;
0 commit comments