summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2004-09-28 22:55:22 +0000
committerMarcus Boerger <helly@php.net>2004-09-28 22:55:22 +0000
commite39f3f3f487c07e6bdac2dca33bc16bb1e86ec23 (patch)
treed5295ba1e8af0ccefe0e2b041426570f10c84dab
parent72b2d1c9ee7d3d7608d55b8db9bfe0ec21981c17 (diff)
downloadphp-git-e39f3f3f487c07e6bdac2dca33bc16bb1e86ec23.tar.gz
Simplify/Optmize magic method calls (__get/__set/__call/__clone/__destruct)
-rw-r--r--Zend/zend_API.c22
-rw-r--r--Zend/zend_API.h3
-rw-r--r--Zend/zend_object_handlers.c117
-rw-r--r--Zend/zend_objects.c20
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);
- }
}
}