]> granicus.if.org Git - php/commitdiff
Try to put an end to the endless number of call_user_function variants.
authorZeev Suraski <zeev@php.net>
Tue, 5 Aug 2003 10:24:40 +0000 (10:24 +0000)
committerZeev Suraski <zeev@php.net>
Tue, 5 Aug 2003 10:24:40 +0000 (10:24 +0000)
zend_call_function() now takes a structure that should contain all of the
necessary information.  If further information is necessary in the future,
then we'll be able to add it without having to introduce a new function.

As for caching - the 2nd, optional argument is a struct that can hold all
of the information that's necessary to invoke the function, including its
handler, scope and object it operates on (if any).  Note that you may only
use a cache if the arguments you provide to zend_call_function() are
identical to the ones of the last call, except for the argument and return
value information.

The recently introduced fast_call_user_function() was removed

I fixed most of the places that used fast_call_user_function() to use caching
but there are still some that need to be fixed (XML and reflection)

Zend/zend_API.h
Zend/zend_execute_API.c
Zend/zend_reflection_api.c
ext/reflection/php_reflection.c

index 5a3abe20c4e62c72ea6302aa2465b2d21e645ea9..41fd8ab32ba69427e2c92b9bce2f7592f2aa44e4 100644 (file)
@@ -265,9 +265,33 @@ ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *valu
 #define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC)
 #define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC)       
 
+
 ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);
 ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC);
-ZEND_API int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC);
+
+typedef struct _zend_fcall_info {
+       size_t size;
+       HashTable *function_table;
+       zval *function_name;
+       HashTable *symbol_table;
+       zval **retval_ptr_ptr;
+       zend_uint param_count;
+       zval ***params;
+       zval **object_pp;
+       zend_bool no_separation;
+} zend_fcall_info;
+
+typedef struct _zend_fcall_info_cache {
+       zend_bool initialized;
+       zend_function *function_handler;
+       zend_class_entry *calling_scope;
+       zval **object_pp;
+} zend_fcall_info_cache;
+
+ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache;
+
+ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC);
+
 
 ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
                                   zend_bool is_ref, int num_symbol_tables, ...);
index 05688f86b1ef2c13d659684f130e8e21695036a1..18b3388ab8081fa4c45e057c480e26c5ec16ab4a 100644 (file)
@@ -40,6 +40,8 @@ ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int
 #ifdef ZEND_WIN32
 #include <process.h>
 /* true global */
+ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { NULL, NULL, NULL, 0 };
+
 static WNDCLASS wc;
 static HWND timeout_window;
 static HANDLE timeout_thread_event;
@@ -481,13 +483,23 @@ int call_user_function(HashTable *function_table, zval **object_pp, zval *functi
 
 int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC)
 {
-       zend_function *function_pointer = NULL;
-
-       return fast_call_user_function(function_table, object_pp, function_name, retval_ptr_ptr, param_count, params, no_separation, symbol_table, &function_pointer TSRMLS_CC);
+       zend_fcall_info fci;
+
+       fci.size = sizeof(fci);
+       fci.function_table = function_table;
+       fci.object_pp = object_pp;
+       fci.function_name = function_name;
+       fci.retval_ptr_ptr = retval_ptr_ptr;
+       fci.param_count = param_count;
+       fci.params = params;
+       fci.no_separation = (zend_bool) no_separation;
+       fci.symbol_table = symbol_table;
+
+       return zend_call_function(&fci, NULL TSRMLS_CC);
 }
 
 
-int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC)
+int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC)
 {
        zend_uint i;
        zval **original_return_value;
@@ -507,55 +519,63 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
        zval *params_array;
        int call_via_handler = 0;
 
+       switch (fci->size) {
+               case sizeof(zend_fcall_info):
+                       break; /* nothing to do currently */
+               default:
+                       zend_error(E_ERROR, "Corrupted fcall_info provided to zend_call_function()");
+                       break;
+       }
+
        /* Initialize execute_data */
        EX(fbc) = NULL;
        EX(object) = NULL;
        EX(Ts) = NULL;
        EX(op_array) = NULL;
        EX(opline) = NULL;
-       *retval_ptr_ptr = NULL;
+       *fci->retval_ptr_ptr = NULL;
 
-       if (function_name->type==IS_ARRAY) { /* assume array($obj, $name) couple */
-               zval **tmp_object_ptr, **tmp_real_function_name;
+       if (!fci_cache || !fci_cache->initialized) {
+               if (fci->function_name->type==IS_ARRAY) { /* assume array($obj, $name) couple */
+                       zval **tmp_object_ptr, **tmp_real_function_name;
 
-               if (zend_hash_index_find(function_name->value.ht, 0, (void **) &tmp_object_ptr)==FAILURE) {
-                       return FAILURE;
+                       if (zend_hash_index_find(fci->function_name->value.ht, 0, (void **) &tmp_object_ptr)==FAILURE) {
+                               return FAILURE;
+                       }
+                       if (zend_hash_index_find(fci->function_name->value.ht, 1, (void **) &tmp_real_function_name)==FAILURE) {
+                               return FAILURE;
+                       }
+                       fci->function_name = *tmp_real_function_name;
+                       SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr);
+                       fci->object_pp = tmp_object_ptr;
+                       (*fci->object_pp)->is_ref = 1;
                }
-               if (zend_hash_index_find(function_name->value.ht, 1, (void **) &tmp_real_function_name)==FAILURE) {
-                       return FAILURE;
+
+               if (fci->object_pp && !*fci->object_pp) {
+                       fci->object_pp = NULL;
                }
-               function_name = *tmp_real_function_name;
-               SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr);
-               object_pp = tmp_object_ptr;
-               (*object_pp)->is_ref = 1;
-       }
 
-       if (object_pp && !*object_pp) {
-               object_pp = NULL;
-       }
+               if (fci->object_pp) {
+                       /* TBI!! new object handlers */
+                       if (Z_TYPE_PP(fci->object_pp) == IS_OBJECT) {
+                               if (!IS_ZEND_STD_OBJECT(**fci->object_pp)) {
+                                       zend_error(E_WARNING, "Cannot use call_user_function on objects without a class entry");
+                                       return FAILURE;
+                               }
 
-       if (object_pp) {
-               /* TBI!! new object handlers */
-               if (Z_TYPE_PP(object_pp) == IS_OBJECT) {
-                       if (!IS_ZEND_STD_OBJECT(**object_pp)) {
-                               zend_error(E_WARNING, "Cannot use call_user_function on objects without a class entry");
-                               return FAILURE;
+                               calling_scope = Z_OBJCE_PP(fci->object_pp);
+                               fci->function_table = &calling_scope->function_table;
+                               EX(object) =  *fci->object_pp;
                        }
-
-                       calling_scope = Z_OBJCE_PP(object_pp);
-                       function_table = &calling_scope->function_table;
-                       EX(object) =  *object_pp;
                }
-       }
 
-       if (*function_pointer == NULL) {
-               if (object_pp) {
-                       if (Z_TYPE_PP(object_pp) == IS_STRING) {
+               if (fci->object_pp) {
+                       if (Z_TYPE_PP(fci->object_pp) == IS_STRING) {
                                zend_class_entry **ce;
                                char *lc_class;
                                int found = FAILURE;
 
-                               lc_class = zend_str_tolower_dup(Z_STRVAL_PP(object_pp), Z_STRLEN_PP(object_pp));
+                               lc_class = zend_str_tolower_dup(Z_STRVAL_PP(fci->object_pp), Z_STRLEN_PP(fci->object_pp));
                                if (EG(active_op_array) && strcmp(lc_class, "self") == 0) {
                                        ce = &(EG(active_op_array)->scope);
                                        found = (*ce != NULL?SUCCESS:FAILURE);
@@ -563,32 +583,32 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
                                        ce = &(EG(active_op_array)->scope->parent);
                                        found = (*ce != NULL?SUCCESS:FAILURE);
                                } else {
-                                       found = zend_lookup_class(lc_class, Z_STRLEN_PP(object_pp), &ce TSRMLS_CC);
+                                       found = zend_lookup_class(lc_class, Z_STRLEN_PP(fci->object_pp), &ce TSRMLS_CC);
                                }
                                efree(lc_class);
                                if (found == FAILURE)
                                        return FAILURE;
 
-                               function_table = &(*ce)->function_table;
+                               fci->function_table = &(*ce)->function_table;
                                calling_scope = *ce;
-                               object_pp = NULL;
+                               fci->object_pp = NULL;
                        }
 
-                       if (function_table == NULL) {
+                       if (fci->function_table == NULL) {
                                return FAILURE;
                        }
                }
 
-               if (function_name->type!=IS_STRING) {
+               if (fci->function_name->type!=IS_STRING) {
                        return FAILURE;
                }
 
-               function_name_lc = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
+               function_name_lc = zend_str_tolower_dup(fci->function_name->value.str.val, fci->function_name->value.str.len);
 
                original_function_state_ptr = EG(function_state_ptr);
-               if (zend_hash_find(function_table, function_name_lc, function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
+               if (zend_hash_find(fci->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
                        /* try calling __call */
-                       if(calling_scope && calling_scope->__call) {
+                       if (calling_scope && calling_scope->__call) {
                                EX(function_state).function = calling_scope->__call;
                                /* prepare params */
                                ALLOC_INIT_ZVAL(method_name);
@@ -603,55 +623,62 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
                        }
                }
                efree(function_name_lc);
-               *function_pointer = EX(function_state).function;
+               EX(function_state).function;
+               if (fci_cache) {
+                       fci_cache->function_handler = EX(function_state).function;
+                       fci_cache->object_pp = fci->object_pp;
+                       fci_cache->calling_scope = calling_scope;
+                       fci_cache->initialized = 1;
+               }
        } else {
-               EX(function_state).function = *function_pointer;
-               calling_scope= EX(function_state).function->common.scope;
+               EX(function_state).function = fci_cache->function_handler;
+               calling_scope = fci_cache->calling_scope;
+               fci->object_pp = fci_cache->object_pp;
        }
        
-       for (i=0; i<param_count; i++) {
+       for (i=0; i<fci->param_count; i++) {
                zval *param;
 
                if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i+1)
-                       && !PZVAL_IS_REF(*params[i])) {
-                       if ((*params[i])->refcount>1) {
+                       && !PZVAL_IS_REF(*fci->params[i])) {
+                       if ((*fci->params[i])->refcount>1) {
                                zval *new_zval;
 
-                               if (no_separation) {
+                               if (fci->no_separation) {
                                        return FAILURE;
                                }
                                ALLOC_ZVAL(new_zval);
-                               *new_zval = **params[i];
+                               *new_zval = **fci->params[i];
                                zval_copy_ctor(new_zval);
                                new_zval->refcount = 1;
-                               (*params[i])->refcount--;
-                               *params[i] = new_zval;
+                               (*fci->params[i])->refcount--;
+                               *fci->params[i] = new_zval;
                        }
-                       (*params[i])->refcount++;
-                       (*params[i])->is_ref = 1;
-                       param = *params[i];
-               } else if (*params[i] != &EG(uninitialized_zval)) {
-                       (*params[i])->refcount++;
-                       param = *params[i];
+                       (*fci->params[i])->refcount++;
+                       (*fci->params[i])->is_ref = 1;
+                       param = *fci->params[i];
+               } else if (*fci->params[i] != &EG(uninitialized_zval)) {
+                       (*fci->params[i])->refcount++;
+                       param = *fci->params[i];
                } else {
                        ALLOC_ZVAL(param);
-                       *param = **(params[i]);
+                       *param = **(fci->params[i]);
                        INIT_PZVAL(param);
                }
-               if(call_via_handler) {
+               if (call_via_handler) {
                        add_next_index_zval(params_array, param);
                } else {
                        zend_ptr_stack_push(&EG(argument_stack), param);
                }
        }
 
-       if(call_via_handler) {
+       if (call_via_handler) {
                zend_ptr_stack_push(&EG(argument_stack), method_name);
                zend_ptr_stack_push(&EG(argument_stack), params_array);
-               param_count = 2;
+               fci->param_count = 2;
        }
 
-       zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL);
+       zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) fci->param_count, NULL);
 
        EG(function_state_ptr) = &EX(function_state);
 
@@ -660,8 +687,8 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
 
        current_this = EG(This);
 
-       if (object_pp) {
-               EG(This) = *object_pp;
+       if (fci->object_pp) {
+               EG(This) = *fci->object_pp;
 
                if (!PZVAL_IS_REF(EG(This))) {
                        EG(This)->refcount++; /* For $this pointer */
@@ -683,8 +710,8 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
 
        if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
                calling_symbol_table = EG(active_symbol_table);
-               if (symbol_table) {
-                       EG(active_symbol_table) = symbol_table;
+               if (fci->symbol_table) {
+                       EG(active_symbol_table) = fci->symbol_table;
                } else {
                        ALLOC_HASHTABLE(EG(active_symbol_table));
                        zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -692,7 +719,7 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
 
                original_return_value = EG(return_value_ptr_ptr);
                original_op_array = EG(active_op_array);
-               EG(return_value_ptr_ptr) = retval_ptr_ptr;
+               EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
                EG(active_op_array) = (zend_op_array *) EX(function_state).function;
                original_opline_ptr = EG(opline_ptr);
                orig_free_op1 = EG(free_op1);
@@ -700,7 +727,7 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
                orig_unary_op = EG(unary_op);
                orig_binary_op = EG(binary_op);
                zend_execute(EG(active_op_array) TSRMLS_CC);
-               if (!symbol_table) {
+               if (!fci->symbol_table) {
                        zend_hash_destroy(EG(active_symbol_table));
                        FREE_HASHTABLE(EG(active_symbol_table));
                }
@@ -713,12 +740,12 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
                EG(unary_op) = orig_unary_op;
                EG(binary_op) = orig_binary_op;
        } else {
-               ALLOC_INIT_ZVAL(*retval_ptr_ptr);
-               ((zend_internal_function *) EX(function_state).function)->handler(param_count, *retval_ptr_ptr, (object_pp?*object_pp:NULL), 1 TSRMLS_CC);
-               INIT_PZVAL(*retval_ptr_ptr);
+               ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
+               ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC);
+               INIT_PZVAL(*fci->retval_ptr_ptr);
        }
        zend_ptr_stack_clear_multiple(TSRMLS_C);
-       if(call_via_handler) {
+       if (call_via_handler) {
                zval_ptr_dtor(&method_name);
                zval_ptr_dtor(&params_array);
        }
@@ -729,11 +756,11 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f
        }
        EG(scope) = current_scope;
        EG(This) = current_this;
-       EG(current_execute_data) = EX(prev_execute_data);                       \
-
-                                                                                                                                                               return SUCCESS;
+       EG(current_execute_data) = EX(prev_execute_data);
+       return SUCCESS;
 }
 
+
 ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
 {
        zval **args[1];
index 648144b9578be0e0d2de4aab0036587fbf81d78f..2a9a4e529292f6f5f486e461d3ab5324636aa899 100644 (file)
@@ -249,7 +249,8 @@ static void _class_string(string *str, zend_class_entry *ce, char *indent TSRMLS
        }
 
        if (ce->num_interfaces) {
-               int i;
+               zend_uint i;
+
                string_printf(str, " implements %s", ce->interfaces[0]->name);
                for (i = 1; i < ce->num_interfaces; ++i) {
                        string_printf(str, ", %s", ce->interfaces[i]->name);
@@ -337,7 +338,7 @@ static void _class_string(string *str, zend_class_entry *ce, char *indent TSRMLS
 
 static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
 {
-       int i;
+       zend_uint i;
        struct _zend_arg_info *arg_info = fptr->common.arg_info;
 
        if (!arg_info) return;
@@ -757,6 +758,7 @@ ZEND_FUNCTION(reflection_function_invoke)
        zval *fname;
        int result;
        int argc = ZEND_NUM_ARGS();
+       zend_fcall_info fci;
        
        METHOD_NOTSTATIC;
        GET_REFLECTION_OBJECT_PTR(fptr);
@@ -774,15 +776,18 @@ ZEND_FUNCTION(reflection_function_invoke)
         */
        MAKE_STD_ZVAL(fname);
        ZVAL_NULL(fname);
-       result = fast_call_user_function(
-               EG(function_table), NULL, fname,
-               &retval_ptr, 
-               argc, 
-               params, 
-               1, 
-               NULL, 
-               &fptr TSRMLS_CC
-       );
+
+       fci.size = sizeof(fci);
+       fci.function_table = EG(function_table);
+       fci.function_name = fname;
+       fci.symbol_table = NULL;
+       fci.object_pp = NULL;
+       fci.retval_ptr_ptr = &retval_ptr;
+       fci.param_count = argc;
+       fci.no_separation = 1;
+       /*fci.function_handler_cache = &fptr;*/
+
+       result = zend_call_function(&fci, NULL TSRMLS_CC);
 
        zval_ptr_dtor(&fname);
        efree(params);
@@ -983,6 +988,7 @@ ZEND_FUNCTION(reflection_method_invoke)
        zval *fname;
        int argc = ZEND_NUM_ARGS();
        int result;
+       zend_fcall_info fci;
        
        METHOD_NOTSTATIC;
 
@@ -1032,17 +1038,19 @@ ZEND_FUNCTION(reflection_method_invoke)
         */
        MAKE_STD_ZVAL(fname);
        ZVAL_NULL(fname);
-       result = fast_call_user_function(
-               EG(function_table), 
-               object_pp,
-               fname,
-               &retval_ptr, 
-               argc - 1, 
-               params+ 1, 
-               1, 
-               NULL, 
-               &mptr TSRMLS_CC
-       );
+
+       fci.size = sizeof(fci);
+       fci.function_table = EG(function_table);
+       fci.function_name = fname;
+       fci.symbol_table = NULL;
+       fci.object_pp = object_pp;
+       fci.retval_ptr_ptr = &retval_ptr;
+       fci.param_count = argc-1;
+       fci.params = params+1;
+       fci.no_separation = 1;
+       /*fci.function_handler_cache = &mptr;*/
+
+       result = zend_call_function(&fci, NULL TSRMLS_CC);
        
        zval_ptr_dtor(&fname);
        efree(params);
@@ -1611,6 +1619,7 @@ ZEND_FUNCTION(reflection_class_newinstance)
        if (ce->constructor) {
                zval ***params;
                zval *fname;
+               zend_fcall_info fci;
 
                params = safe_emalloc(sizeof(zval **), argc, 0);
                if (zend_get_parameters_array_ex(argc, params) == FAILURE) {
@@ -1625,9 +1634,19 @@ ZEND_FUNCTION(reflection_class_newinstance)
                 */
                MAKE_STD_ZVAL(fname);
                ZVAL_NULL(fname);
-               if (fast_call_user_function(EG(function_table), &return_value, fname,
-                                                                  &retval_ptr, argc, params, 
-                                                                  1, NULL, &ce->constructor TSRMLS_CC) == FAILURE) {
+
+               fci.size = sizeof(fci);
+               fci.function_table = EG(function_table);
+               fci.function_name = fname;
+               fci.symbol_table = NULL;
+               fci.object_pp = &return_value;
+               fci.retval_ptr_ptr = &retval_ptr;
+               fci.param_count = argc;
+               fci.params = params;
+               fci.no_separation = 1;
+               /*fci.function_handler_cache = &ce->constructor;*/
+
+               if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
                        efree(params);
                        zval_ptr_dtor(&fname);
                        zend_error(E_WARNING, "Invokation of %s's constructor failed\n", ce->name);
index 648144b9578be0e0d2de4aab0036587fbf81d78f..2a9a4e529292f6f5f486e461d3ab5324636aa899 100644 (file)
@@ -249,7 +249,8 @@ static void _class_string(string *str, zend_class_entry *ce, char *indent TSRMLS
        }
 
        if (ce->num_interfaces) {
-               int i;
+               zend_uint i;
+
                string_printf(str, " implements %s", ce->interfaces[0]->name);
                for (i = 1; i < ce->num_interfaces; ++i) {
                        string_printf(str, ", %s", ce->interfaces[i]->name);
@@ -337,7 +338,7 @@ static void _class_string(string *str, zend_class_entry *ce, char *indent TSRMLS
 
 static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
 {
-       int i;
+       zend_uint i;
        struct _zend_arg_info *arg_info = fptr->common.arg_info;
 
        if (!arg_info) return;
@@ -757,6 +758,7 @@ ZEND_FUNCTION(reflection_function_invoke)
        zval *fname;
        int result;
        int argc = ZEND_NUM_ARGS();
+       zend_fcall_info fci;
        
        METHOD_NOTSTATIC;
        GET_REFLECTION_OBJECT_PTR(fptr);
@@ -774,15 +776,18 @@ ZEND_FUNCTION(reflection_function_invoke)
         */
        MAKE_STD_ZVAL(fname);
        ZVAL_NULL(fname);
-       result = fast_call_user_function(
-               EG(function_table), NULL, fname,
-               &retval_ptr, 
-               argc, 
-               params, 
-               1, 
-               NULL, 
-               &fptr TSRMLS_CC
-       );
+
+       fci.size = sizeof(fci);
+       fci.function_table = EG(function_table);
+       fci.function_name = fname;
+       fci.symbol_table = NULL;
+       fci.object_pp = NULL;
+       fci.retval_ptr_ptr = &retval_ptr;
+       fci.param_count = argc;
+       fci.no_separation = 1;
+       /*fci.function_handler_cache = &fptr;*/
+
+       result = zend_call_function(&fci, NULL TSRMLS_CC);
 
        zval_ptr_dtor(&fname);
        efree(params);
@@ -983,6 +988,7 @@ ZEND_FUNCTION(reflection_method_invoke)
        zval *fname;
        int argc = ZEND_NUM_ARGS();
        int result;
+       zend_fcall_info fci;
        
        METHOD_NOTSTATIC;
 
@@ -1032,17 +1038,19 @@ ZEND_FUNCTION(reflection_method_invoke)
         */
        MAKE_STD_ZVAL(fname);
        ZVAL_NULL(fname);
-       result = fast_call_user_function(
-               EG(function_table), 
-               object_pp,
-               fname,
-               &retval_ptr, 
-               argc - 1, 
-               params+ 1, 
-               1, 
-               NULL, 
-               &mptr TSRMLS_CC
-       );
+
+       fci.size = sizeof(fci);
+       fci.function_table = EG(function_table);
+       fci.function_name = fname;
+       fci.symbol_table = NULL;
+       fci.object_pp = object_pp;
+       fci.retval_ptr_ptr = &retval_ptr;
+       fci.param_count = argc-1;
+       fci.params = params+1;
+       fci.no_separation = 1;
+       /*fci.function_handler_cache = &mptr;*/
+
+       result = zend_call_function(&fci, NULL TSRMLS_CC);
        
        zval_ptr_dtor(&fname);
        efree(params);
@@ -1611,6 +1619,7 @@ ZEND_FUNCTION(reflection_class_newinstance)
        if (ce->constructor) {
                zval ***params;
                zval *fname;
+               zend_fcall_info fci;
 
                params = safe_emalloc(sizeof(zval **), argc, 0);
                if (zend_get_parameters_array_ex(argc, params) == FAILURE) {
@@ -1625,9 +1634,19 @@ ZEND_FUNCTION(reflection_class_newinstance)
                 */
                MAKE_STD_ZVAL(fname);
                ZVAL_NULL(fname);
-               if (fast_call_user_function(EG(function_table), &return_value, fname,
-                                                                  &retval_ptr, argc, params, 
-                                                                  1, NULL, &ce->constructor TSRMLS_CC) == FAILURE) {
+
+               fci.size = sizeof(fci);
+               fci.function_table = EG(function_table);
+               fci.function_name = fname;
+               fci.symbol_table = NULL;
+               fci.object_pp = &return_value;
+               fci.retval_ptr_ptr = &retval_ptr;
+               fci.param_count = argc;
+               fci.params = params;
+               fci.no_separation = 1;
+               /*fci.function_handler_cache = &ce->constructor;*/
+
+               if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
                        efree(params);
                        zval_ptr_dtor(&fname);
                        zend_error(E_WARNING, "Invokation of %s's constructor failed\n", ce->name);