summaryrefslogtreecommitdiff
path: root/Zend/zend_interfaces.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-06-08 17:10:24 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-06-09 16:21:54 +0200
commit257dbb04501391e0ac57e66aebe2e4d25dcc5c91 (patch)
tree2ea10373c366bc81468d3172ed49fb4860741a90 /Zend/zend_interfaces.c
parentbcada03f48b242930ded84d66c1f0b826176f696 (diff)
downloadphp-git-257dbb04501391e0ac57e66aebe2e4d25dcc5c91.tar.gz
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.
Diffstat (limited to 'Zend/zend_interfaces.c')
-rw-r--r--Zend/zend_interfaces.c61
1 files changed, 16 insertions, 45 deletions
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(&params[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)) {