From: Nikita Popov Date: Mon, 8 Jun 2020 15:10:24 +0000 (+0200) Subject: Add zend_call_known_function() API family X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=257dbb04501391e0ac57e66aebe2e4d25dcc5c91;p=php Add zend_call_known_function() API family This adds the following APIs: void zend_call_known_function( zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, int param_count, zval *params); void zend_call_known_instance_method( zend_function *fn, zend_object *object, zval *retval_ptr, int param_count, zval *params); void zend_call_known_instance_method_with_0_params( zend_function *fn, zend_object *object, zval *retval_ptr); void zend_call_known_instance_method_with_1_params( zend_function *fn, zend_object *object, zval *retval_ptr, zval *param); void zend_call_known_instance_method_with_2_params( zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2); These are used to perform a call if you already have the zend_function you want to call. zend_call_known_function() is the base API, the rest are just really thin wrappers around it for the common case of instance method calls. Closes GH-5692. --- diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 944bef850d..ae391d98e5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -563,6 +563,37 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache); +/* Call the provided zend_function with the given params. + * If retval_ptr is NULL, the return value is discarded. + * If object is NULL, this must be a free function or static call. + * called_scope must be provided for instance and static method calls. */ +ZEND_API void zend_call_known_function( + zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, + uint32_t param_count, zval *params); + +/* Call the provided zend_function instance method on an object. */ +static zend_always_inline void zend_call_known_instance_method( + zend_function *fn, zend_object *object, zval *retval_ptr, + uint32_t param_count, zval *params) +{ + zend_call_known_function(fn, object, object->ce, retval_ptr, param_count, params); +} + +static zend_always_inline void zend_call_known_instance_method_with_0_params( + zend_function *fn, zend_object *object, zval *retval_ptr) +{ + zend_call_known_instance_method(fn, object, retval_ptr, 0, NULL); +} + +static zend_always_inline void zend_call_known_instance_method_with_1_params( + zend_function *fn, zend_object *object, zval *retval_ptr, zval *param) +{ + zend_call_known_instance_method(fn, object, retval_ptr, 1, param); +} + +ZEND_API void zend_call_known_instance_method_with_2_params( + zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2); + ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...); ZEND_API int zend_delete_global_variable(zend_string *name); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 57eb010821..594186682b 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -922,7 +922,7 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { zend_string *str, *file = NULL; zend_long line = 0; - zend_call_method_with_0_params(Z_OBJ(exception), ce_exception, &ex->ce->__tostring, "__tostring", &tmp); + zend_call_known_instance_method_with_0_params(ex->ce->__tostring, Z_OBJ(exception), &tmp); if (!EG(exception)) { if (Z_TYPE(tmp) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name)); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1b48bed125..c5626a0df3 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -861,6 +861,51 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } /* }}} */ +ZEND_API void zend_call_known_function( + zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, + uint32_t param_count, zval *params) +{ + zval retval; + zend_fcall_info fci; + zend_fcall_info_cache fcic; + + ZEND_ASSERT(fn && "zend_function must be passed!"); + + fci.size = sizeof(fci); + fci.object = object; + fci.retval = retval_ptr ? retval_ptr : &retval; + fci.param_count = param_count; + fci.params = params; + fci.no_separation = 1; + ZVAL_UNDEF(&fci.function_name); /* Unused */ + + fcic.function_handler = fn; + fcic.object = object; + fcic.called_scope = called_scope; + + int result = zend_call_function(&fci, &fcic); + if (UNEXPECTED(result == FAILURE)) { + if (!EG(exception)) { + zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", + fn->common.scope ? ZSTR_VAL(fn->common.scope->name) : "", + fn->common.scope ? "::" : "", ZSTR_VAL(fn->common.function_name)); + } + } + + if (!retval_ptr) { + zval_ptr_dtor(&retval); + } +} + +ZEND_API void zend_call_known_instance_method_with_2_params( + zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2) +{ + zval params[2]; + ZVAL_COPY_VALUE(¶ms[0], param1); + ZVAL_COPY_VALUE(¶ms[1], param2); + zend_call_known_instance_method(fn, object, retval_ptr, 2, params); +} + ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */ { zend_class_entry *ce = NULL; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 6ad81c0805..2a6d70dc58 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -32,12 +32,10 @@ ZEND_API zend_class_entry *zend_ce_stringable; /* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ -ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, uint32_t param_count, zval* arg1, zval* arg2) { - int result; - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval retval; + zend_function *fn; + zend_class_entry *called_scope; zval params[2]; if (param_count > 0) { @@ -47,68 +45,43 @@ ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, z ZVAL_COPY_VALUE(¶ms[1], arg2); } - fci.size = sizeof(fci); - fci.object = object; - fci.retval = retval_ptr ? retval_ptr : &retval; - fci.param_count = param_count; - fci.params = params; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - if (!obj_ce) { obj_ce = object ? object->ce : NULL; } if (!fn_proxy || !*fn_proxy) { if (EXPECTED(obj_ce)) { - fcic.function_handler = zend_hash_str_find_ptr( + fn = zend_hash_str_find_ptr( &obj_ce->function_table, function_name, function_name_len); - if (UNEXPECTED(fcic.function_handler == NULL)) { + if (UNEXPECTED(fn == NULL)) { /* error at c-level */ zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for method %s::%s", ZSTR_VAL(obj_ce->name), function_name); } } else { - fcic.function_handler = zend_fetch_function_str(function_name, function_name_len); - if (UNEXPECTED(fcic.function_handler == NULL)) { + fn = zend_fetch_function_str(function_name, function_name_len); + if (UNEXPECTED(fn == NULL)) { /* error at c-level */ zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for function %s", function_name); } } if (fn_proxy) { - *fn_proxy = fcic.function_handler; + *fn_proxy = fn; } } else { - fcic.function_handler = *fn_proxy; + fn = *fn_proxy; } if (object) { - fcic.called_scope = object->ce; + called_scope = object->ce; } else { - zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); - + called_scope = zend_get_called_scope(EG(current_execute_data)); if (obj_ce && (!called_scope || !instanceof_function(called_scope, obj_ce))) { - fcic.called_scope = obj_ce; - } else { - fcic.called_scope = called_scope; + called_scope = obj_ce; } } - fcic.object = object; - result = zend_call_function(&fci, &fcic); - if (result == FAILURE) { - /* error at c-level */ - if (!obj_ce) { - obj_ce = object ? object->ce : NULL; - } - if (!EG(exception)) { - zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name); - } - } - if (!retval_ptr) { - zval_ptr_dtor(&retval); - return NULL; - } + zend_call_known_function(fn, object, called_scope, retval_ptr, param_count, params); return retval_ptr; } /* }}} */ @@ -390,8 +363,7 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *b zval retval; int result; - zend_call_method_with_0_params(Z_OBJ_P(object), ce, &ce->serialize_func, "serialize", &retval); - + zend_call_known_instance_method_with_0_params(ce->serialize_func, Z_OBJ_P(object), &retval); if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) { result = FAILURE; @@ -430,9 +402,8 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns } ZVAL_STRINGL(&zdata, (char*)buf, buf_len); - - zend_call_method_with_1_params(Z_OBJ_P(object), ce, &ce->unserialize_func, "unserialize", NULL, &zdata); - + zend_call_known_instance_method_with_1_params( + ce->unserialize_func, Z_OBJ_P(object), NULL, &zdata); zval_ptr_dtor(&zdata); if (EG(exception)) { diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index dbdcd2a074..fd3275b2a4 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -38,7 +38,7 @@ typedef struct _zend_user_iterator { zval value; } zend_user_iterator; -ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2); +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, uint32_t param_count, zval* arg1, zval* arg2); #define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \ zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 4a8b24233a..05944bbbdf 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -149,7 +149,7 @@ ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) / return object->handlers->get_properties(object); } - zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval); + zend_call_known_instance_method_with_0_params(ce->__debugInfo, object, &retval); if (Z_TYPE(retval) == IS_ARRAY) { if (!Z_REFCOUNTED(retval)) { *is_temp = 1; @@ -177,35 +177,13 @@ ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) / static void zend_std_call_getter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */ { - zend_class_entry *ce = zobj->ce; zend_class_entry *orig_fake_scope = EG(fake_scope); - zend_fcall_info fci; - zend_fcall_info_cache fcic; zval member; EG(fake_scope) = NULL; - /* __get handler is called with one argument: - property name - - it should return whether the call was successful or not - */ - ZVAL_STR(&member, prop_name); - - fci.size = sizeof(fci); - fci.object = zobj; - fci.retval = retval; - fci.param_count = 1; - fci.params = &member; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = ce->__get; - fcic.called_scope = ce; - fcic.object = zobj; - - zend_call_function(&fci, &fcic); + zend_call_known_instance_method_with_1_params(zobj->ce->__get, zobj, retval, &member); EG(fake_scope) = orig_fake_scope; } @@ -213,37 +191,14 @@ static void zend_std_call_getter(zend_object *zobj, zend_string *prop_name, zval static void zend_std_call_setter(zend_object *zobj, zend_string *prop_name, zval *value) /* {{{ */ { - zend_class_entry *ce = zobj->ce; zend_class_entry *orig_fake_scope = EG(fake_scope); - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval args[2], ret; + zval args[2]; EG(fake_scope) = NULL; - /* __set handler is called with two arguments: - property name - value to be set - */ - ZVAL_STR(&args[0], prop_name); ZVAL_COPY_VALUE(&args[1], value); - ZVAL_UNDEF(&ret); - - fci.size = sizeof(fci); - fci.object = zobj; - fci.retval = &ret; - fci.param_count = 2; - fci.params = args; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = ce->__set; - fcic.called_scope = ce; - fcic.object = zobj; - - zend_call_function(&fci, &fcic); - zval_ptr_dtor(&ret); + zend_call_known_instance_method(zobj->ce->__set, zobj, NULL, 2, args); EG(fake_scope) = orig_fake_scope; } @@ -251,35 +206,13 @@ static void zend_std_call_setter(zend_object *zobj, zend_string *prop_name, zval static void zend_std_call_unsetter(zend_object *zobj, zend_string *prop_name) /* {{{ */ { - zend_class_entry *ce = zobj->ce; zend_class_entry *orig_fake_scope = EG(fake_scope); - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval ret, member; + zval member; EG(fake_scope) = NULL; - /* __unset handler is called with one argument: - property name - */ - ZVAL_STR(&member, prop_name); - ZVAL_UNDEF(&ret); - - fci.size = sizeof(fci); - fci.object = zobj; - fci.retval = &ret; - fci.param_count = 1; - fci.params = &member; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = ce->__unset; - fcic.called_scope = ce; - fcic.object = zobj; - - zend_call_function(&fci, &fcic); - zval_ptr_dtor(&ret); + zend_call_known_instance_method_with_1_params(zobj->ce->__unset, zobj, NULL, &member); EG(fake_scope) = orig_fake_scope; } @@ -287,35 +220,13 @@ static void zend_std_call_unsetter(zend_object *zobj, zend_string *prop_name) /* static void zend_std_call_issetter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */ { - zend_class_entry *ce = zobj->ce; zend_class_entry *orig_fake_scope = EG(fake_scope); - zend_fcall_info fci; - zend_fcall_info_cache fcic; zval member; EG(fake_scope) = NULL; - /* __isset handler is called with one argument: - property name - - it should return whether the property is set or not - */ - ZVAL_STR(&member, prop_name); - - fci.size = sizeof(fci); - fci.object = zobj; - fci.retval = retval; - fci.param_count = 1; - fci.params = &member; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = ce->__isset; - fcic.called_scope = ce; - fcic.object = zobj; - - zend_call_function(&fci, &fcic); + zend_call_known_instance_method_with_1_params(zobj->ce->__isset, zobj, retval, &member); EG(fake_scope) = orig_fake_scope; } @@ -1803,7 +1714,7 @@ ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, zend_class_entry *fake_scope = EG(fake_scope); EG(fake_scope) = NULL; GC_ADDREF(readobj); - zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval); + zend_call_known_instance_method_with_0_params(ce->__tostring, readobj, &retval); zend_object_release(readobj); EG(fake_scope) = fake_scope; if (EXPECTED(Z_TYPE(retval) == IS_STRING)) { diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 13a6b45a7c..f25983ece3 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -98,9 +98,6 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) if (destructor) { zend_object *old_exception; zend_class_entry *orig_fake_scope; - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval ret; if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { @@ -162,22 +159,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) orig_fake_scope = EG(fake_scope); EG(fake_scope) = NULL; - ZVAL_UNDEF(&ret); - - fci.size = sizeof(fci); - fci.object = object; - fci.retval = &ret; - fci.param_count = 0; - fci.params = NULL; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = destructor; - fcic.called_scope = object->ce; - fcic.object = object; - - zend_call_function(&fci, &fcic); - zval_ptr_dtor(&ret); + zend_call_known_instance_method_with_0_params(destructor, object, NULL); if (old_exception) { if (EG(exception)) { @@ -264,28 +246,8 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, } if (old_object->ce->clone) { - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval ret; - GC_ADDREF(new_object); - - ZVAL_UNDEF(&ret); - - fci.size = sizeof(fci); - fci.object = new_object; - fci.retval = &ret; - fci.param_count = 0; - fci.params = NULL; - fci.no_separation = 1; - ZVAL_UNDEF(&fci.function_name); /* Unused */ - - fcic.function_handler = new_object->ce->clone; - fcic.called_scope = new_object->ce; - fcic.object = new_object; - - zend_call_function(&fci, &fcic); - zval_ptr_dtor(&ret); + zend_call_known_instance_method_with_0_params(new_object->ce->clone, new_object, NULL); OBJ_RELEASE(new_object); } } diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index 45fe97d509..186c2597f4 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -1016,7 +1016,8 @@ U_CFUNC PHP_FUNCTION(intlcal_from_date_time) if (!(Z_TYPE_P(zv_arg) == IS_OBJECT && instanceof_function( Z_OBJCE_P(zv_arg), php_date_get_date_ce()))) { object_init_ex(&zv_tmp, php_date_get_date_ce()); - zend_call_method_with_1_params(Z_OBJ(zv_tmp), NULL, &Z_OBJCE(zv_tmp)->constructor, "__construct", NULL, zv_arg); + zend_call_known_instance_method_with_1_params( + Z_OBJCE(zv_tmp)->constructor, Z_OBJ(zv_tmp), NULL, zv_arg); zv_datetime = &zv_tmp; if (EG(exception)) { zend_object_store_ctor_failed(Z_OBJ(zv_tmp)); @@ -1130,7 +1131,8 @@ U_CFUNC PHP_FUNCTION(intlcal_to_date_time) /* Finally, instantiate object and call constructor */ object_init_ex(return_value, php_date_get_date_ce()); - zend_call_method_with_2_params(Z_OBJ_P(return_value), NULL, &Z_OBJCE_P(return_value)->constructor, "__construct", NULL, &ts_zval, timezone_zval); + zend_call_known_instance_method_with_2_params( + Z_OBJCE_P(return_value)->constructor, Z_OBJ_P(return_value), NULL, &ts_zval, timezone_zval); if (EG(exception)) { intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, "intlcal_to_date_time: DateTime constructor has thrown exception", diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp index b3d447f5d5..63d5b05746 100644 --- a/ext/intl/timezone/timezone_class.cpp +++ b/ext/intl/timezone/timezone_class.cpp @@ -96,7 +96,8 @@ U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, goto error; } ZVAL_STR(&arg, u8str); - zend_call_method_with_1_params(Z_OBJ_P(ret), NULL, &Z_OBJCE_P(ret)->constructor, "__construct", NULL, &arg); + zend_call_known_instance_method_with_1_params( + Z_OBJCE_P(ret)->constructor, Z_OBJ_P(ret), NULL, &arg); if (EG(exception)) { spprintf(&message, 0, "%s: DateTimeZone constructor threw exception", func); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 351d342c53..d273e1d519 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1242,8 +1242,8 @@ PHP_METHOD(Phar, __construct) ZVAL_STRINGL(&arg1, fname, fname_len); ZVAL_LONG(&arg2, flags); - zend_call_method_with_2_params(Z_OBJ_P(zobj), Z_OBJCE_P(zobj), - &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2); + zend_call_known_instance_method_with_2_params(spl_ce_RecursiveDirectoryIterator->constructor, + Z_OBJ_P(zobj), NULL, &arg1, &arg2); zval_ptr_dtor(&arg1); @@ -1764,8 +1764,8 @@ PHP_METHOD(Phar, buildFromDirectory) ZVAL_STRINGL(&arg, dir, dir_len); ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS); - zend_call_method_with_2_params(Z_OBJ(iter), spl_ce_RecursiveDirectoryIterator, - &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2); + zend_call_known_instance_method_with_2_params(spl_ce_RecursiveDirectoryIterator->constructor, + Z_OBJ(iter), NULL, &arg, &arg2); zval_ptr_dtor(&arg); if (EG(exception)) { @@ -1780,8 +1780,8 @@ PHP_METHOD(Phar, buildFromDirectory) RETURN_THROWS(); } - zend_call_method_with_1_params(Z_OBJ(iteriter), spl_ce_RecursiveIteratorIterator, - &spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, &iter); + zend_call_known_instance_method_with_1_params(spl_ce_RecursiveIteratorIterator->constructor, + Z_OBJ(iteriter), NULL, &iter); if (EG(exception)) { zval_ptr_dtor(&iter); @@ -1803,8 +1803,8 @@ PHP_METHOD(Phar, buildFromDirectory) ZVAL_STRINGL(&arg2, regex, regex_len); - zend_call_method_with_2_params(Z_OBJ(regexiter), spl_ce_RegexIterator, - &spl_ce_RegexIterator->constructor, "__construct", NULL, &iteriter, &arg2); + zend_call_known_instance_method_with_2_params(spl_ce_RegexIterator->constructor, + Z_OBJ(regexiter), NULL, &iteriter, &arg2); zval_ptr_dtor(&arg2); } @@ -2256,7 +2256,7 @@ its_ok: ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len); - zend_call_method_with_1_params(Z_OBJ(ret), ce, &ce->constructor, "__construct", NULL, &arg1); + zend_call_known_instance_method_with_1_params(ce->constructor, Z_OBJ(ret), NULL, &arg1); zval_ptr_dtor(&arg1); return Z_OBJ(ret); } @@ -4539,8 +4539,8 @@ PHP_METHOD(PharFileInfo, __construct) ZVAL_STRINGL(&arg1, fname, fname_len); - zend_call_method_with_1_params(Z_OBJ_P(zobj), Z_OBJCE_P(zobj), - &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1); + zend_call_known_instance_method_with_1_params(spl_ce_SplFileInfo->constructor, + Z_OBJ_P(zobj), NULL, &arg1); zval_ptr_dtor(&arg1); } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index e7296b8008..1f29ff59e4 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4754,7 +4754,6 @@ ZEND_METHOD(ReflectionClass, isInstance) Returns an instance of this class */ ZEND_METHOD(ReflectionClass, newInstance) { - zval retval; reflection_object *intern; zend_class_entry *ce, *old_scope; zend_function *constructor; @@ -4773,9 +4772,7 @@ ZEND_METHOD(ReflectionClass, newInstance) /* Run the constructor if there is one */ if (constructor) { zval *params = NULL; - int ret, i, num_args = 0; - zend_fcall_info fci; - zend_fcall_info_cache fcc; + int i, num_args = 0; if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name)); @@ -4792,20 +4789,8 @@ ZEND_METHOD(ReflectionClass, newInstance) Z_TRY_ADDREF(params[i]); } - fci.size = sizeof(fci); - ZVAL_UNDEF(&fci.function_name); - fci.object = Z_OBJ_P(return_value); - fci.retval = &retval; - fci.param_count = num_args; - fci.params = params; - fci.no_separation = 1; - - fcc.function_handler = constructor; - fcc.called_scope = Z_OBJCE_P(return_value); - fcc.object = Z_OBJ_P(return_value); + zend_call_known_instance_method(constructor, Z_OBJ_P(return_value), NULL, num_args, params); - ret = zend_call_function(&fci, &fcc); - zval_ptr_dtor(&retval); for (i = 0; i < num_args; i++) { zval_ptr_dtor(¶ms[i]); } @@ -4813,11 +4798,6 @@ ZEND_METHOD(ReflectionClass, newInstance) if (EG(exception)) { zend_object_store_ctor_failed(Z_OBJ_P(return_value)); } - if (ret == FAILURE) { - php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name)); - zval_ptr_dtor(return_value); - RETURN_NULL(); - } } else if (ZEND_NUM_ARGS()) { zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name)); } @@ -4851,10 +4831,10 @@ ZEND_METHOD(ReflectionClass, newInstanceWithoutConstructor) Returns an instance of this class */ ZEND_METHOD(ReflectionClass, newInstanceArgs) { - zval retval, *val; + zval *val; reflection_object *intern; zend_class_entry *ce, *old_scope; - int ret, i, argc = 0; + int i, argc = 0; HashTable *args; zend_function *constructor; @@ -4880,8 +4860,6 @@ ZEND_METHOD(ReflectionClass, newInstanceArgs) /* Run the constructor if there is one */ if (constructor) { zval *params = NULL; - zend_fcall_info fci; - zend_fcall_info_cache fcc; if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name)); @@ -4898,20 +4876,8 @@ ZEND_METHOD(ReflectionClass, newInstanceArgs) } ZEND_HASH_FOREACH_END(); } - fci.size = sizeof(fci); - ZVAL_UNDEF(&fci.function_name); - fci.object = Z_OBJ_P(return_value); - fci.retval = &retval; - fci.param_count = argc; - fci.params = params; - fci.no_separation = 1; + zend_call_known_instance_method(constructor, Z_OBJ_P(return_value), NULL, argc, params); - fcc.function_handler = constructor; - fcc.called_scope = Z_OBJCE_P(return_value); - fcc.object = Z_OBJ_P(return_value); - - ret = zend_call_function(&fci, &fcc); - zval_ptr_dtor(&retval); if (params) { for (i = 0; i < argc; i++) { zval_ptr_dtor(¶ms[i]); @@ -4922,12 +4888,6 @@ ZEND_METHOD(ReflectionClass, newInstanceArgs) if (EG(exception)) { zend_object_store_ctor_failed(Z_OBJ_P(return_value)); } - if (ret == FAILURE) { - zval_ptr_dtor(&retval); - php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name)); - zval_ptr_dtor(return_value); - RETURN_NULL(); - } } else if (argc) { zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name)); } @@ -6487,15 +6447,7 @@ ZEND_METHOD(ReflectionAttribute, getArguments) static int call_attribute_constructor(zend_class_entry *ce, zend_object *obj, zval *args, uint32_t argc) /* {{{ */ { - zend_fcall_info fci; - zend_fcall_info_cache fcc; - - zend_function *ctor; - zval retval; - int ret; - - ctor = ce->constructor; - + zend_function *ctor = ce->constructor; ZEND_ASSERT(ctor != NULL); if (!(ctor->common.fn_flags & ZEND_ACC_PUBLIC)) { @@ -6503,31 +6455,13 @@ static int call_attribute_constructor(zend_class_entry *ce, zend_object *obj, zv return FAILURE; } - fci.size = sizeof(fci); - ZVAL_UNDEF(&fci.function_name); - fci.object = obj; - fci.retval = &retval; - fci.params = args; - fci.param_count = argc; - fci.no_separation = 1; - - fcc.function_handler = ctor; - fcc.called_scope = ce; - fcc.object = obj; - - ret = zend_call_function(&fci, &fcc); - + zend_call_known_instance_method(ctor, obj, NULL, argc, args); if (EG(exception)) { zend_object_store_ctor_failed(obj); + return FAILURE; } - zval_ptr_dtor(&retval); - - if (ret != SUCCESS) { - zend_throw_error(NULL, "Failed to invoke constructor of attribute class '%s'", ZSTR_VAL(ce->name)); - } - - return EG(exception) ? FAILURE : SUCCESS; + return SUCCESS; } /* }}} */ diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 206d393b7e..a9069c6191 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -1070,7 +1070,8 @@ static int do_cli(int argc, char **argv) /* {{{ */ memset(&execute_data, 0, sizeof(zend_execute_data)); EG(current_execute_data) = &execute_data; - zend_call_method_with_1_params(Z_OBJ(ref), pce, &pce->constructor, "__construct", NULL, &arg); + zend_call_known_instance_method_with_1_params( + pce->constructor, Z_OBJ(ref), NULL, &arg); if (EG(exception)) { zval tmp, *msg, rv; diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 14e09d7243..2f0e8e2440 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -726,7 +726,7 @@ static inline void phpdbg_handle_exception(void) /* {{{ */ EG(exception) = NULL; ZVAL_OBJ(&zv, ex); - zend_call_method_with_0_params(ex, ex->ce, &ex->ce->__tostring, "__tostring", &tmp); + zend_call_known_instance_method_with_0_params(ex->ce->__tostring, ex, &tmp); file = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("file"), 1, &rv)); line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv));