Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:1736 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 26282 invoked from network); 19 May 2003 18:26:30 -0000 Received: from unknown (HELO carmine.bestweb.net) (209.94.102.73) by pb1.pair.com with SMTP; 19 May 2003 18:26:30 -0000 Received: from [192.168.1.102] (ip216-179-71-153.cust.bestweb.net [216.179.71.153]) by carmine.bestweb.net (Postfix) with ESMTP id 38773232C8 for ; Mon, 19 May 2003 13:26:30 -0500 (EST) To: internals@lists.php.net Content-Type: multipart/mixed; boundary="=-yzsFgHcnQZ+ePfyKMnsm" Organization: Message-ID: <1053363650.790.178.camel@hasele> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.2.4 Date: 19 May 2003 13:00:50 -0400 Subject: fast_call_user_function From: sterling@bumblebury.com (Sterling Hughes) --=-yzsFgHcnQZ+ePfyKMnsm Content-Type: text/plain Content-Transfer-Encoding: 7bit Hi, Attached is a patch which adds a new function fast_call_user_function(). fast_call_user_function allows you to cache the lookups of function calls, this way when you call the same function repeatedly (as in usort() or any callback code), it doesn't need to be looked up over and over and over and over and over again. I've ported usort() and friends over to using fast_call_user_function() and it resulted in around a 15% speedup. If no one objects I'm going to commit this to Zend, and then make the necessary changes in the code (at least in ext/standard). -Sterling -- "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg." - Bjarne Stroustrup --=-yzsFgHcnQZ+ePfyKMnsm Content-Disposition: attachment; filename=fast_call_user_function.diff Content-Type: text/plain; name=fast_call_user_function.diff; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit ? fast_call_user_function Index: zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.138 diff -u -r1.138 zend_API.h --- zend_API.h 4 May 2003 22:49:31 -0000 1.138 +++ zend_API.h 19 May 2003 18:05:09 -0000 @@ -252,6 +252,7 @@ ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int 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, int 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, int param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer 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: zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.202 diff -u -r1.202 zend_execute_API.c --- zend_execute_API.c 12 May 2003 18:54:05 -0000 1.202 +++ zend_execute_API.c 19 May 2003 18:05:19 -0000 @@ -522,9 +522,15 @@ return ex_retval; } - int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int 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); +} + +int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC) +{ int i; zval **original_return_value; HashTable *calling_symbol_table; @@ -549,70 +555,79 @@ EX(opline) = NULL; *retval_ptr_ptr = NULL; - if (function_name->type==IS_ARRAY) { /* assume array($obj, $name) couple */ - zval **tmp_object_ptr, **tmp_real_function_name; + /** + * Function name lookup code + * + */ + if (*function_pointer == NULL) { + if (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(function_name->value.ht, 1, (void **) &tmp_real_function_name)==FAILURE) { - return FAILURE; - } - 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 (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"); + if (zend_hash_index_find(function_name->value.ht, 0, (void **) &tmp_object_ptr)==FAILURE) { return FAILURE; } - - calling_scope = Z_OBJCE_PP(object_pp); - function_table = &calling_scope->function_table; - EX(object) = *object_pp; - } else if (Z_TYPE_PP(object_pp) == IS_STRING) { - zend_class_entry **ce; - char *lc_class; - int found; - - lc_class = estrndup(Z_STRVAL_PP(object_pp), Z_STRLEN_PP(object_pp)); - zend_str_tolower(lc_class, Z_STRLEN_PP(object_pp)); - found = zend_lookup_class(lc_class, Z_STRLEN_PP(object_pp), &ce TSRMLS_CC); - efree(lc_class); - if (found == FAILURE) + if (zend_hash_index_find(function_name->value.ht, 1, (void **) &tmp_real_function_name)==FAILURE) { return FAILURE; + } + function_name = *tmp_real_function_name; + SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr); + object_pp = tmp_object_ptr; + (*object_pp)->is_ref = 1; + } - function_table = &(*ce)->function_table; - calling_scope = *ce; + if (object_pp && !*object_pp) { object_pp = NULL; - } else - return FAILURE; - } + } - if (function_name->type!=IS_STRING) { - 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(object_pp); + function_table = &calling_scope->function_table; + EX(object) = *object_pp; + } else if (Z_TYPE_PP(object_pp) == IS_STRING) { + zend_class_entry **ce; + char *lc_class; + int found; + + lc_class = estrndup(Z_STRVAL_PP(object_pp), Z_STRLEN_PP(object_pp)); + zend_str_tolower(lc_class, Z_STRLEN_PP(object_pp)); + found = zend_lookup_class(lc_class, Z_STRLEN_PP(object_pp), &ce TSRMLS_CC); + efree(lc_class); + if (found == FAILURE) + return FAILURE; + + function_table = &(*ce)->function_table; + calling_scope = *ce; + object_pp = NULL; + } else + return FAILURE; + } - function_name_copy = *function_name; - zval_copy_ctor(&function_name_copy); - zend_str_tolower(function_name_copy.value.str.val, function_name_copy.value.str.len); + if (function_name->type!=IS_STRING) { + return FAILURE; + } - original_function_state_ptr = EG(function_state_ptr); - if (zend_hash_find(function_table, function_name_copy.value.str.val, function_name_copy.value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { + function_name_copy = *function_name; + zval_copy_ctor(&function_name_copy); + zend_str_tolower(function_name_copy.value.str.val, function_name_copy.value.str.len); + + original_function_state_ptr = EG(function_state_ptr); + if (zend_hash_find(function_table, function_name_copy.value.str.val, function_name_copy.value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { + zval_dtor(&function_name_copy); + return FAILURE; + } zval_dtor(&function_name_copy); - return FAILURE; + *function_pointer = EX(function_state).function; + } else { + EX(function_state).function = *function_pointer; } - zval_dtor(&function_name_copy); - + for (i=0; i