diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 7dea050f66d..9c48ad15883 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -2,6 +2,7 @@ PHP 8.0 INTERNALS UPGRADE NOTES 1. Internal API changes a. Object Handlers API + b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler 2. Build system changes a. Abstract @@ -14,10 +15,15 @@ PHP 8.0 INTERNALS UPGRADE NOTES 1. Internal API changes ======================== - a. Object Handlers API and some related functions, e.g. zend_call_method() and - zend_objects_clone_obj() were changed to receive zend_object* instead of - zval* and zend_string* instead of zval* for property names. + a. Object Handlers API and some related functions, e.g. zend_call_method() and + zend_objects_clone_obj() were changed to receive zend_object* instead of + zval* and zend_string* instead of zval* for property names. + b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler + were removed. ZEND_INTERNAL_FUNCTION with ZEND_ACC_CALL_VIA_HANDLER and + defined "handler" callback should be used instead. This "handler" callback + should also take care about function cleanup. See ext/zend_test/test.c + for example. ======================== 2. Build system changes diff --git a/Zend/tests/overloaded_func_001.phpt b/Zend/tests/overloaded_func_001.phpt index 31585d505a3..7fc435f9208 100644 --- a/Zend/tests/overloaded_func_001.phpt +++ b/Zend/tests/overloaded_func_001.phpt @@ -6,10 +6,10 @@ if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded'); ?> --FILE-- test()); var_dump(_ZendTestClass::test()); ?> ---EXPECTF-- -Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d -Stack trace: -#0 {main} - thrown in %soverloaded_func_001.php on line %d +--EXPECT-- +string(4) "test" +string(4) "test" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b51d6bd408c..0b745161ff5 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3014,8 +3014,7 @@ get_function_via_handler: (!fcc->function_handler->common.scope || !instanceof_function(ce_org, fcc->function_handler->common.scope))) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3206,11 +3205,8 @@ check_func: ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error); if (fcc == &fcc_local && fcc->function_handler && - ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3322,12 +3318,8 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name)); } if (fcc.function_handler && - ((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) || - fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || - fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) { - if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) { - zend_string_release_ex(fcc.function_handler->common.function_name, 0); - } + (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + zend_string_release_ex(fcc.function_handler->common.function_name, 0); zend_free_trampoline(fcc.function_handler); } return 1; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 62d17b4e117..6c1be2fdc00 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -875,9 +875,7 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_INTERNAL_FUNCTION 1 #define ZEND_USER_FUNCTION 2 -#define ZEND_OVERLOADED_FUNCTION 3 #define ZEND_EVAL_CODE 4 -#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 /* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */ #define ZEND_USER_CODE(type) ((type & 1) == 0) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index edaed2c63f0..e33506d7755 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4069,43 +4069,6 @@ already_compiled: } /* }}} */ -ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */ -{ - zend_function *fbc = call->func; - zend_object *object; - - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - return 0; - } - - object = Z_OBJ(call->This); - - ZVAL_NULL(ret); - - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - - zend_vm_stack_free_args(call); - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - - return 1; -} -/* }}} */ - static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(array_ptr); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index a73982ab911..76f7d09f431 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -375,8 +375,6 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data); ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); -ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret); - #define CACHE_ADDR(num) \ ((void**)((char*)EX_RUN_TIME_CACHE() + (num))) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index fb6faad8afc..de85e2ea6cb 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -772,8 +772,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else if (func->type == ZEND_INTERNAL_FUNCTION) { + } else { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; + + ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION); ZVAL_NULL(fci->retval); call->prev_execute_data = EG(current_execute_data); call->return_value = NULL; /* this is not a constructor call */ @@ -796,30 +798,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ZVAL_NULL(fci->retval); - - /* Not sure what should be done here if it's a static method */ - if (fci->object) { - call->prev_execute_data = EG(current_execute_data); - EG(current_execute_data) = call; - fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval); - EG(current_execute_data) = call->prev_execute_data; - } else { - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - } - - zend_vm_stack_free_args(call); - - if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(func->common.function_name, 0); - } - efree(func); - - if (EG(exception)) { - zval_ptr_dtor(fci->retval); - ZVAL_UNDEF(fci->retval); - } } zend_vm_stack_free_call_frame(call); diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index bb3cf1b6a25..7e920c00d83 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -44,7 +44,6 @@ static const zend_object_handlers iterator_object_handlers = { NULL, /* unset dim */ NULL, /* props get */ NULL, /* method get */ - NULL, /* call */ NULL, /* get ctor */ NULL, /* get class name */ NULL, /* compare */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index eb853064c2b..520610327f3 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1845,7 +1845,6 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_unset_dimension, /* unset_dimension */ zend_std_get_properties, /* get_properties */ zend_std_get_method, /* get_method */ - NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ zend_std_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 64356bcb04a..ff4f025970b 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -120,7 +120,6 @@ typedef zend_array *(*zend_object_get_properties_for_t)(zend_object *object, zen /* args on stack! */ /* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this. */ -typedef int (*zend_object_call_method_t)(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS); typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key); typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object); @@ -171,7 +170,6 @@ struct _zend_object_handlers { zend_object_unset_dimension_t unset_dimension; /* required */ zend_object_get_properties_t get_properties; /* required */ zend_object_get_method_t get_method; /* required */ - zend_object_call_method_t call_method; /* optional */ zend_object_get_constructor_t get_constructor; /* required */ zend_object_get_class_name_t get_class_name; /* required */ zend_object_compare_t compare_objects; /* optional */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9b808a6e120..5114b2275c0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4019,9 +4019,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -4053,22 +4054,6 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(ret); - } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(ret); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 13e096363d3..a7a17c64af4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -963,9 +963,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -997,22 +998,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); - if (!0) { - zval_ptr_dtor(ret); - } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 0 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (!0) { zval_ptr_dtor(ret); } @@ -1084,9 +1069,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1118,22 +1104,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); - if (!1) { - zval_ptr_dtor(ret); - } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 1 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - if (!1) { zval_ptr_dtor(ret); } diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index 6e5cc8c4d8b..4f64b5502e8 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -246,11 +246,42 @@ static void function_dtor(zval *zv) static PHP_FUNCTION(com_method_handler) { zval *object = getThis(); + zend_string *method = EX(func)->common.function_name; + zval *args = NULL; + php_com_dotnet_object *obj = CDNO_FETCH(object); + int nargs; + VARIANT v; + int ret = FAILURE; - Z_OBJ_HANDLER_P(object, call_method)( - ((zend_internal_function*)EX(func))->function_name, - Z_OBJ_P(object), - INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (V_VT(&obj->v) != VT_DISPATCH) { + goto exit; + } + + nargs = ZEND_NUM_ARGS(); + + if (nargs) { + args = (zval *)safe_emalloc(sizeof(zval), nargs, 0); + zend_get_parameters_array_ex(nargs, args); + } + + VariantInit(&v); + + if (SUCCESS == php_com_do_invoke_byref(obj, (zend_internal_function*)EX(func), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args)) { + php_com_zval_from_variant(return_value, &v, obj->code_page); + ret = SUCCESS; + VariantClear(&v); + } + + if (args) { + efree(args); + } + +exit: + /* Cleanup trampoline */ + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE); + zend_string_release(EX(func)->common.function_name); + zend_free_trampoline(EX(func)); + EX(func) = NULL; } static zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key) @@ -270,7 +301,8 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name /* check cache */ if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) { - f.type = ZEND_OVERLOADED_FUNCTION; + memset(&f, 0, sizeof(zend_internal_function)); + f.type = ZEND_INTERNAL_FUNCTION; f.num_args = 0; f.arg_info = NULL; f.scope = obj->ce; @@ -345,6 +377,7 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name if (fptr) { /* duplicate this into a new chunk of emalloc'd memory, * since the engine will efree it */ + zend_string_addref(fptr->function_name); func = emalloc(sizeof(*fptr)); memcpy(func, fptr, sizeof(*fptr)); @@ -354,40 +387,6 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name return NULL; } -static int com_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *args = NULL; - php_com_dotnet_object *obj = (php_com_dotnet_object*)object; - int nargs; - VARIANT v; - int ret = FAILURE; - - if (V_VT(&obj->v) != VT_DISPATCH) { - return FAILURE; - } - - nargs = ZEND_NUM_ARGS(); - - if (nargs) { - args = (zval *)safe_emalloc(sizeof(zval), nargs, 0); - zend_get_parameters_array_ex(nargs, args); - } - - VariantInit(&v); - - if (SUCCESS == php_com_do_invoke_byref(obj, (zend_internal_function*)EX(func), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args)) { - php_com_zval_from_variant(return_value, &v, obj->code_page); - ret = SUCCESS; - VariantClear(&v); - } - - if (args) { - efree(args); - } - - return ret; -} - static zend_function *com_constructor_get(zend_object *object) { php_com_dotnet_object *obj = (php_com_dotnet_object *) object; @@ -554,7 +553,6 @@ zend_object_handlers php_com_object_handlers = { com_dimension_delete, com_properties_get, com_method_get, - com_call_method, com_constructor_get, com_class_name_get, com_objects_compare, diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index 7ce57ce915d..225786bde88 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -319,11 +319,6 @@ static zend_function *saproxy_method_get(zend_object **object, zend_string *name return NULL; } -static int saproxy_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) -{ - return FAILURE; -} - static zend_function *saproxy_constructor_get(zend_object *object) { /* user cannot instantiate */ @@ -410,7 +405,6 @@ zend_object_handlers php_com_saproxy_handlers = { saproxy_dimension_delete, saproxy_properties_get, saproxy_method_get, - saproxy_call_method, saproxy_constructor_get, saproxy_class_name_get, saproxy_objects_compare, diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 50820499cfe..9a84fe70679 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2656,11 +2656,6 @@ static zend_function *row_method_get( return fbc; } -static int row_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) -{ - return FAILURE; -} - static zend_function *row_get_ctor(zend_object *object) { zend_throw_exception_ex(php_pdo_get_exception(), 0, "You may not create a PDORow manually"); @@ -2739,7 +2734,6 @@ void pdo_stmt_init(void) pdo_row_object_handlers.unset_dimension = row_dim_delete; pdo_row_object_handlers.get_properties_for = row_get_properties_for; pdo_row_object_handlers.get_method = row_method_get; - pdo_row_object_handlers.call_method = row_call_method; pdo_row_object_handlers.get_constructor = row_get_ctor; pdo_row_object_handlers.get_class_name = row_get_classname; pdo_row_object_handlers.compare_objects = row_compare; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 92d9d9138a2..f834c947e6f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2341,9 +2341,7 @@ ZEND_METHOD(reflection_parameter, __construct) position= (int)Z_LVAL_P(parameter); if (position < 0 || (uint32_t)position >= num_args) { if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { - if (fptr->type != ZEND_OVERLOADED_FUNCTION) { - zend_string_release_ex(fptr->common.function_name, 0); - } + zend_string_release_ex(fptr->common.function_name, 0); zend_free_trampoline(fptr); } if (is_closure) { @@ -2380,9 +2378,7 @@ ZEND_METHOD(reflection_parameter, __construct) } if (position == -1) { if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { - if (fptr->type != ZEND_OVERLOADED_FUNCTION) { - zend_string_release_ex(fptr->common.function_name, 0); - } + zend_string_release_ex(fptr->common.function_name, 0); zend_free_trampoline(fptr); } if (is_closure) { diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index dcd9a05f9e3..ecefa1c2c09 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1367,47 +1367,6 @@ static zend_function *spl_dual_it_get_method(zend_object **object, zend_string * return function_handler; } -#if MBO_0 -int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) -{ - zval ***func_params, func; - zval retval; - int arg_count; - int current = 0; - int success; - void **p; - spl_dual_it_object *intern; - - intern = Z_SPLDUAL_IT_P(ZEND_THIS); - - ZVAL_STRING(&func, method, 0); - - p = EG(argument_stack).top_element-2; - arg_count = (zend_ulong) *p; - - func_params = safe_emalloc(sizeof(zval **), arg_count, 0); - - current = 0; - while (arg_count-- > 0) { - func_params[current] = (zval **) p - (arg_count-current); - current++; - } - arg_count = current; /* restore */ - - if (call_user_function_ex(EG(function_table), NULL, &func, &retval, arg_count, func_params, 0, NULL) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - RETURN_ZVAL(&retval, 0, 0); - - success = SUCCESS; - } else { - zend_throw_error(NULL, "Unable to call %s::%s()", intern->inner.ce->name, method); - success = FAILURE; - } - - efree(func_params); - return success; -} -#endif - #define SPL_CHECK_CTOR(intern, classname) \ if (intern->dit_type == DIT_Unknown) { \ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Classes derived from %s must call %s::__construct()", \ @@ -3682,7 +3641,6 @@ PHP_MINIT_FUNCTION(spl_iterators) memcpy(&spl_handlers_dual_it, &std_object_handlers, sizeof(zend_object_handlers)); spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std); spl_handlers_dual_it.get_method = spl_dual_it_get_method; - /*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/ spl_handlers_dual_it.clone_obj = NULL; spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor; spl_handlers_dual_it.free_obj = spl_dual_it_free_storage; diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 53af862d244..48aea6856a0 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -50,7 +50,13 @@ ZEND_END_ARG_INFO() ZEND_FUNCTION(zend_test_func) { - /* dummy */ + RETVAL_STR_COPY(EX(func)->common.function_name); + + /* Cleanup trampoline */ + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE); + zend_string_release(EX(func)->common.function_name); + zend_free_trampoline(EX(func)); + EX(func) = NULL; } ZEND_FUNCTION(zend_test_array_return) @@ -144,41 +150,45 @@ static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ /* }}} */ static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ { - zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); - fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; + zend_internal_function *fptr; + + if (EXPECTED(EG(trampoline).common.function_name == NULL)) { + fptr = &EG(trampoline); + } else { + fptr = emalloc(sizeof(zend_internal_function)); + } + memset(fptr, 0, sizeof(zend_internal_function)); + fptr->type = ZEND_INTERNAL_FUNCTION; fptr->num_args = 1; - fptr->arg_info = NULL; fptr->scope = (*object)->ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER; fptr->function_name = zend_string_copy(name); fptr->handler = ZEND_FN(zend_test_func); - zend_set_function_arg_flags((zend_function*)fptr); return (zend_function*)fptr; } /* }}} */ static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ { - zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); - fptr->type = ZEND_OVERLOADED_FUNCTION; + zend_internal_function *fptr; + + if (EXPECTED(EG(trampoline).common.function_name == NULL)) { + fptr = &EG(trampoline); + } else { + fptr = emalloc(sizeof(zend_internal_function)); + } + memset(fptr, 0, sizeof(zend_internal_function)); + fptr->type = ZEND_INTERNAL_FUNCTION; fptr->num_args = 1; - fptr->arg_info = NULL; fptr->scope = ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC; - fptr->function_name = name; + fptr->function_name = zend_string_copy(name); fptr->handler = ZEND_FN(zend_test_func); - zend_set_function_arg_flags((zend_function*)fptr); return (zend_function*)fptr; } /* }}} */ -static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { - RETVAL_STR(zend_string_copy(method)); - return 0; -} -/* }}} */ - static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ { RETURN_TRUE; } @@ -239,7 +249,6 @@ PHP_MINIT_FUNCTION(zend_test) memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_test_class_handlers.get_method = zend_test_class_method_get; - zend_test_class_handlers.call_method = zend_test_class_call_method; INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods); zend_test_trait = zend_register_internal_class(&class_entry);