diff options
author | Marcus Boerger <helly@php.net> | 2004-09-28 22:55:22 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2004-09-28 22:55:22 +0000 |
commit | e39f3f3f487c07e6bdac2dca33bc16bb1e86ec23 (patch) | |
tree | d5295ba1e8af0ccefe0e2b041426570f10c84dab | |
parent | 72b2d1c9ee7d3d7608d55b8db9bfe0ec21981c17 (diff) | |
download | php-git-e39f3f3f487c07e6bdac2dca33bc16bb1e86ec23.tar.gz |
Simplify/Optmize magic method calls (__get/__set/__call/__clone/__destruct)
-rw-r--r-- | Zend/zend_API.c | 22 | ||||
-rw-r--r-- | Zend/zend_API.h | 3 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 117 | ||||
-rw-r--r-- | Zend/zend_objects.c | 20 |
4 files changed, 46 insertions, 116 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 01d6d49f07..e9925bd1ac 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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)); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 12312938c0..e5d3927c9b 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -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) \ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 5417a517b2..142c144dd7 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 162905256b..30f6297c3d 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -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); - } } } |