]> granicus.if.org Git - php/commitdiff
Simplify/Optmize magic method calls (__get/__set/__call/__clone/__destruct)
authorMarcus Boerger <helly@php.net>
Tue, 28 Sep 2004 22:55:22 +0000 (22:55 +0000)
committerMarcus Boerger <helly@php.net>
Tue, 28 Sep 2004 22:55:22 +0000 (22:55 +0000)
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_object_handlers.c
Zend/zend_objects.c

index 01d6d49f07c2912915de12c7e5e8da0f508a0c63..e9925bd1ac183e9cf772cfe4cf8a99ee029e5f58 100644 (file)
@@ -159,6 +159,28 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr
 }
 
 
+ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC)
+{
+       void **p;
+       int arg_count;
+
+       p = EG(argument_stack).top_element-2;
+       arg_count = (ulong) *p;
+
+       if (param_count>arg_count) {
+               return FAILURE;
+       }
+
+       while (param_count-->0) {
+               zval **param = (zval **) p-(arg_count--);
+               zval_add_ref(param);
+               add_next_index_zval(argument_array, *param);            
+       }
+
+       return SUCCESS;
+}
+
+
 ZEND_API void zend_wrong_param_count(TSRMLS_D)
 {
        zend_error(E_WARNING, "Wrong parameter count for %s()", get_active_function_name(TSRMLS_C));
index 12312938c07599fd23ad74a67780bcb9d81bb890..e5d3927c9bfc2fa550482316438dc6f4c04bdd3b 100644 (file)
@@ -146,6 +146,9 @@ ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument
 ZEND_API int zend_get_parameters_ex(int param_count, ...);
 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC);
 
+/* internal function to efficiently copy parameters when executing __call() */
+ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC);
+
 #define zend_get_parameters_array(ht, param_count, argument_array)                     \
        _zend_get_parameters_array(ht, param_count, argument_array TSRMLS_CC)
 #define zend_get_parameters_array_ex(param_count, argument_array)                      \
index 5417a517b25444230b5bcdb63d88c649737fa385..142c144dd70d7919952b83c9db71a28a8a226752 100644 (file)
@@ -58,40 +58,16 @@ static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
 
 static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
 {
-       zval **call_args[1];
        zval *retval = NULL;
-       zval __get_name;
-       int call_result;
+       zend_class_entry *ce = Z_OBJCE_P(object);
        
-       /* __get handler is called with two arguments:
-          property name
-          return value for the object (by reference)
+       /* __get handler is called with one argument:
+             property name
 
           it should return whether the call was successfull or not
        */
-       INIT_PZVAL(&__get_name);
-       ZVAL_STRINGL(&__get_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1, 0);
-
-       call_args[0] = &member;
-
-       /* go call the __get handler */
-       call_result = call_user_function_ex(NULL,
-                                                                               &object,
-                                                                               &__get_name,
-                                                                               &retval,
-                                                                               1, call_args,
-                                                                               0, NULL TSRMLS_CC);
-
-       /* 
-          call_result is if call_user_function gone OK.
-          retval returns the value that is received
-       */
-       
+       zend_call_method_with_1_params(&object, ce, &ce->__get, ZEND_GET_FUNC_NAME, &retval, member);
 
-       if (call_result == FAILURE) {
-               zend_error(E_ERROR, "Could not call __get handler for class %s", Z_OBJCE_P(object)->name);
-               return NULL;
-       }
        if (retval) {
                retval->refcount--;
        }
@@ -101,43 +77,19 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
 
 static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC)
 {
-       zval **call_args[2];
        zval *retval = NULL;
-       zval __set_name;
-       int call_result;
        int ret;
+       zend_class_entry *ce = Z_OBJCE_P(object);
        
+       value->refcount++;
+
        /* __set handler is called with two arguments:
-          property name
-          value to be set
+            property name
+            value to be set
 
           it should return whether the call was successfull or not
        */
-       INIT_PZVAL(&__set_name);
-       ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1, 0);
-
-       call_args[0] = &member;
-       value->refcount++;
-       call_args[1] = &value;
-
-       /* go call the __set handler */
-       call_result = call_user_function_ex(NULL,
-                                                                               &object,
-                                                                               &__set_name,
-                                                                               &retval,
-                                                                               2, call_args,
-                                                                               0, NULL TSRMLS_CC);
-
-       /* 
-          call_result is if call_user_function gone OK.
-          retval shows if __get method went OK.
-       */
-       
-
-       if (call_result == FAILURE) {
-               zend_error(E_ERROR, "Could not call __set handler for class %s", Z_OBJCE_P(object)->name);
-               return FAILURE;
-       }
+       zend_call_method_with_2_params(&object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value);
 
        zval_ptr_dtor(&value);
 
@@ -525,18 +477,18 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
 
 ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
 {
-       zval ***args;
        zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function;
-       zval method_name, method_args, __call_name;
+       zval method_name, method_args;
        zval *method_name_ptr, *method_args_ptr;
-       zval **call_args[2];
        zval *method_result_ptr = NULL;
-       int i, call_result;
+       zend_class_entry *ce = Z_OBJCE_P(this_ptr);
        
-       args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **));
+       method_args_ptr = &method_args;
+       INIT_PZVAL(method_args_ptr);
+       array_init(method_args_ptr);
 
-       if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
-               efree(args);
+       if (zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE) {
+               zval_dtor(method_args_ptr);
                zend_error(E_ERROR, "Cannot get arguments for __call");
                RETURN_FALSE;
        }
@@ -545,50 +497,19 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
        INIT_PZVAL(method_name_ptr);
        ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
 
-       method_args_ptr = &method_args;
-       INIT_PZVAL(method_args_ptr);
-       array_init(method_args_ptr);
-
-       for(i=0; i<ZEND_NUM_ARGS(); i++) {
-               zval_add_ref(args[i]);
-               add_next_index_zval(method_args_ptr, *args[i]);
-       }
-
-       efree(args);
-       
-       INIT_PZVAL(&__call_name);
-       ZVAL_STRINGL(&__call_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1, 0);
-       
        /* __call handler is called with two arguments:
           method name
           array of method parameters
 
        */
-       call_args[0] = &method_name_ptr;
-       call_args[1] = &method_args_ptr;
-
-       /* go call the __call handler */
-       call_result = call_user_function_ex(NULL,
-                                                                               &this_ptr,
-                                                                               &__call_name,
-                                                                               &method_result_ptr,
-                                                                               2, call_args,
-                                                                               0, NULL TSRMLS_CC);
-
-       /* call_result is if call_user_function gone OK.
-          method_result_ptr is the true result of the called method
-       */
-       
+       zend_call_method_with_2_params(&this_ptr, ce, &ce->__call, ZEND_CALL_FUNC_NAME, &method_result_ptr, method_name_ptr, method_args_ptr);
+
        if (method_result_ptr) {
                *return_value = *method_result_ptr;
                zval_copy_ctor(return_value);
                zval_ptr_dtor(&method_result_ptr);
        }
        
-       if (call_result == FAILURE) {
-               zend_error(E_ERROR, "Could not call __call handler for class %s", Z_OBJCE_P(this_ptr)->name);
-       }
-
        /* now destruct all auxiliaries */
        zval_dtor(method_args_ptr);
        zval_dtor(method_name_ptr);
index 162905256b170830c9a92d72f0134eba1c86132a..30f6297c3dc690498fd22e7a608b3c408a6d266f 100644 (file)
@@ -75,7 +75,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
                 */
                old_exception = EG(exception);
                EG(exception) = NULL;
-               zend_call_method_with_0_params(&obj, object->ce, NULL, "__destruct", NULL);
+               zend_call_method_with_0_params(&obj, object->ce, &object->ce->destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
                if (old_exception) {
                        if (EG(exception)) {
                                zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active", object->ce->name);
@@ -116,31 +116,15 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_va
        zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
        if (old_object->ce->clone) {
                zval *new_obj;
-               zval *clone_func_name;
-               zval *retval_ptr;
-               HashTable symbol_table;
 
                MAKE_STD_ZVAL(new_obj);
                new_obj->type = IS_OBJECT;
                new_obj->value.obj = new_obj_val;
                zval_copy_ctor(new_obj);
 
-               /* FIXME: Optimize this so that we use the old_object->ce->clone function pointer instead of the name */
-               MAKE_STD_ZVAL(clone_func_name);
-               clone_func_name->type = IS_STRING;
-               clone_func_name->value.str.val = estrndup("__clone", sizeof("__clone")-1);
-               clone_func_name->value.str.len = sizeof("__clone")-1;
+               zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
 
-               ZEND_INIT_SYMTABLE(&symbol_table);
-               
-               call_user_function_ex(NULL, &new_obj, clone_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC);
-
-               zend_hash_destroy(&symbol_table);
                zval_ptr_dtor(&new_obj);
-               zval_ptr_dtor(&clone_func_name);
-               if(retval_ptr) {
-                       zval_ptr_dtor(&retval_ptr);
-               }
        }
 }