]> granicus.if.org Git - php/commitdiff
- Separate other kinds of function calls too.
authorAndi Gutmans <andi@php.net>
Fri, 4 Jan 2002 08:05:21 +0000 (08:05 +0000)
committerAndi Gutmans <andi@php.net>
Fri, 4 Jan 2002 08:05:21 +0000 (08:05 +0000)
- Significantly improve performance of function calls by moving lowercasing
- the function name to compile-time when possible.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c

index df80201335fb9265eadb602cee60b07afb617ee5..3cbb04f513b927b00a9c9d1e97be26d3793d2679 100644 (file)
@@ -693,7 +693,13 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
        *result = opline->result;
 }
 
-       
+static void zend_lowercase_znode_if_const(znode *z)
+{
+       if (z->op_type == IS_CONST) {
+               zend_str_tolower(z->u.constant.value.str.val, z->u.constant.value.str.len);
+       }
+}
+
 void zend_do_free(znode *op1 TSRMLS_DC)
 {
        if (op1->op_type==IS_TMP_VAR) {
@@ -909,8 +915,9 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
                zend_do_extended_fcall_begin(TSRMLS_C); 
                return;
        }
-       last_op->opcode = ZEND_INIT_FCALL_BY_NAME;
-       last_op->extended_value = ZEND_MEMBER_FUNC_CALL;
+       last_op->opcode = ZEND_INIT_METHOD_CALL;
+       zend_lowercase_znode_if_const(&last_op->op2);
+       // last_op->extended_value = ZEND_MEMBER_FUNC_CALL;
        left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME;
 
        /*opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -1011,10 +1018,11 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *function
        unsigned char *ptr = NULL;
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = ZEND_INIT_FCALL_BY_NAME;
+       opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
        opline->op1 = *class_name;
+       zend_lowercase_znode_if_const(function_name);
        opline->op2 = *function_name;
-       opline->extended_value = ZEND_MEMBER_FUNC_CALL;
+       //opline->extended_value = ZEND_MEMBER_FUNC_CALL;
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
 }
 
index a9f69d9c2f5e9de51fb60a726fe7e795d5b4af4f..7d91ba6c4ec860baa5f127df67f393b80597c900 100644 (file)
@@ -546,6 +546,9 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_CLONE                                     111
 
 #define ZEND_INIT_CTOR_CALL                    112
+#define ZEND_INIT_METHOD_CALL          113
+#define ZEND_INIT_STATIC_METHOD_CALL 114
+
 /* end of block */
 
 
index 15202bd6e653fcc8670d15ec5bd483cf265cb839..6d0acd6282c3749a7cbdb3adef0df4106e6b9bc5 100644 (file)
@@ -1563,11 +1563,134 @@ binary_assign_op_addr: {
                                        EX(calling_namespace) = Z_OBJCE_P(EX(object).ptr);
                                        NEXT_OPCODE();
                                }
-                       case ZEND_INIT_FCALL_BY_NAME: {
+                       case ZEND_INIT_METHOD_CALL:
+                               {
                                        zval *function_name;
                                        zend_function *function;
                                        HashTable *active_function_table;
                                        zval tmp;
+                                       zend_bool is_const;
+                                       char *function_name_strval;
+                                       int function_name_strlen;
+
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+
+                                       is_const = (EX(opline)->op2.op_type == IS_CONST);
+
+                                       if (is_const) {
+                                               function_name_strval = EX(opline)->op2.u.constant.value.str.val;
+                                               function_name_strlen = EX(opline)->op2.u.constant.value.str.len;
+                                       } else {
+                                               function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+
+                                               tmp = *function_name;
+                                               zval_copy_ctor(&tmp);
+                                               convert_to_string(&tmp);
+                                               function_name = &tmp;
+                                               zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
+
+                                               function_name_strval = tmp.value.str.val;
+                                               function_name_strlen = tmp.value.str.len;
+                                       }
+                                       
+                                       EX(calling_namespace) = EG(namespace);
+
+                                       EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                                                       
+                                       /* Nuked overloaded method code. This will be redone differently */
+
+                                       if (EX(object).ptr && EX(object).ptr->type == IS_OBJECT) {
+                                               active_function_table = &Z_OBJCE_P(EX(object).ptr)->function_table;     
+                                       } else {
+                                               zend_error(E_ERROR, "Call to a member function on a non-object");
+                                       }
+                                       if (!PZVAL_IS_REF(EX(object).ptr)) {
+                                               EX(object).ptr->refcount++; /* For $this pointer */
+                                       } else {
+                                               zval *this_ptr;
+                                               ALLOC_ZVAL(this_ptr);
+                                               *this_ptr = *EX(object).ptr;
+                                               INIT_PZVAL(this_ptr);
+                                               zval_copy_ctor(this_ptr);
+                                               EX(object).ptr = this_ptr;
+                                       }
+
+                                       EX(calling_namespace) = Z_OBJCE_P(EX(object).ptr);
+
+                                       if (zend_hash_find(active_function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) {
+                                               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+                                       }
+
+                                       if (!is_const) {
+                                               zval_dtor(&tmp);
+                                               FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
+                                       }
+
+                                       EX(fbc) = function;
+                                       NEXT_OPCODE();
+                               }
+                       case ZEND_INIT_STATIC_METHOD_CALL:
+                               {
+                                       zval *function_name;
+                                       zend_function *function;
+                                       zval tmp;
+                                       zval **object_ptr_ptr;
+                                       zend_class_entry *ce;
+                                       zend_bool is_const;
+                                       char *function_name_strval;
+                                       int function_name_strlen;
+
+                                       zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
+
+                                       is_const = (EX(opline)->op2.op_type == IS_CONST);
+
+                                       if (is_const) {
+                                               function_name_strval = EX(opline)->op2.u.constant.value.str.val;
+                                               function_name_strlen = EX(opline)->op2.u.constant.value.str.len;
+                                       } else {
+                                               function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+
+                                               tmp = *function_name;
+                                               zval_copy_ctor(&tmp);
+                                               convert_to_string(&tmp);
+                                               function_name = &tmp;
+                                               zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
+
+                                               function_name_strval = tmp.value.str.val;
+                                               function_name_strlen = tmp.value.str.len;
+                                       }
+                                       
+                                       EX(calling_namespace) = EG(namespace);
+                                       
+                                       if (zend_hash_find(EG(active_symbol_table), "this", sizeof("this"), (void **) &object_ptr_ptr)==FAILURE) {
+                                               EX(object).ptr=NULL;
+                                       } else {
+                                               /* We assume that "this" is already is_ref and pointing to the object.
+                                                  If it isn't then tough */
+                                               EX(object).ptr = *object_ptr_ptr;
+                                               EX(object).ptr->refcount++; /* For this pointer */
+                                       }
+                                       ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
+
+                                       EX(calling_namespace) = ce;
+
+                                       if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) {
+                                               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+                                       }
+
+                                       if (!is_const) {
+                                               zval_dtor(&tmp);
+                                       }
+
+                                       EX(fbc) = function;
+
+                                       NEXT_OPCODE();
+                               }
+                       case ZEND_INIT_FCALL_BY_NAME:
+                               {
+                                       zval *function_name;
+                                       zend_function *function;
+                                       zval tmp;
 
                                        zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object).ptr);
 
@@ -1581,90 +1704,25 @@ binary_assign_op_addr: {
                                        
                                        EX(calling_namespace) = EG(namespace);
 
-                                       if (EX(opline)->op1.op_type != IS_UNUSED) {
-                                               if (EX(opline)->op1 .op_type==IS_CONST) { /* used for class::function() */
-                                                       zval **object_ptr_ptr;
-
-                                                       if (zend_hash_find(EG(active_symbol_table), "this", sizeof("this"), (void **) &object_ptr_ptr)==FAILURE) {
-                                                               EX(object).ptr=NULL;
-                                                       } else {
-                                                               /* We assume that "this" is already is_ref and pointing to the object.
-                                                                  If it isn't then tough */
-                                                               EX(object).ptr = *object_ptr_ptr;
-                                                               EX(object).ptr->refcount++; /* For this pointer */
-                                                       }
-
-                                                       {
-                                                               zend_class_entry *ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
-                                                               active_function_table = &ce->function_table;
-                                                               EX(calling_namespace) = ce;
-                                                       }
-                                               } else { /* used for member function calls */
-                                                       EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
-                                                       
-                                                       if ((!EX(object).ptr && EX(Ts)[EX(opline)->op1.u.var].EA.type==IS_OVERLOADED_OBJECT)                                                            
-                                                               || ((EX(object).ptr && EX(object).ptr->type==IS_OBJECT) && Z_OBJCE_P(EX(object).ptr)->handle_function_call)) { /* overloaded function call */
-                                                               zend_overloaded_element overloaded_element;
-
-                                                               overloaded_element.element = *function_name;
-                                                               overloaded_element.type = OE_IS_METHOD;
-
-                                                               if (EX(object).ptr) {
-                                                                       EX(Ts)[EX(opline)->op1.u.var].EA.data.overloaded_element.object = EX(object).ptr;
-                                                                       EX(Ts)[EX(opline)->op1.u.var].EA.data.overloaded_element.type = BP_VAR_NA;
-                                                                       EX(Ts)[EX(opline)->op1.u.var].EA.data.overloaded_element.elements_list = (zend_llist *) emalloc(sizeof(zend_llist));
-                                                                       zend_llist_init(EX(Ts)[EX(opline)->op1.u.var].EA.data.overloaded_element.elements_list, sizeof(zend_overloaded_element), NULL, 0);
-                                                               }
-                                                               zend_llist_add_element(EX(Ts)[EX(opline)->op1.u.var].EA.data.overloaded_element.elements_list, &overloaded_element);
-                                                               EX(fbc) = (zend_function *) emalloc(sizeof(zend_function));
-                                                               EX(fbc)->type = ZEND_OVERLOADED_FUNCTION;
-                                                               EX(fbc)->common.arg_types = NULL;
-                                                               EX(fbc)->overloaded_function.var = EX(opline)->op1.u.var;
-                                                               goto overloaded_function_call_cont;
-                                                       }
+                                       EX(object).ptr = NULL;
 
-                                                       if (EX(object).ptr && EX(object).ptr->type == IS_OBJECT) {
-                                                               active_function_table = &Z_OBJCE_P(EX(object).ptr)->function_table;     
-                                                       } else {
-                                                               zend_error(E_ERROR, "Call to a member function on a non-object");
-                                                       }
-                                                       if (!PZVAL_IS_REF(EX(object).ptr)) {
-                                                               EX(object).ptr->refcount++; /* For $this pointer */
-                                                       } else {
-                                                               zval *this_ptr;
-                                                               ALLOC_ZVAL(this_ptr);
-                                                               *this_ptr = *EX(object).ptr;
-                                                               INIT_PZVAL(this_ptr);
-                                                               zval_copy_ctor(this_ptr);
-                                                               EX(object).ptr = this_ptr;
+                                       do {
+                                               if (EG(namespace)) {
+                                                       if (zend_hash_find(&EG(namespace)->function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function) == SUCCESS) {
+                                                               break;
                                                        }
-                                                       //active_function_table = &Z_OBJCE_P(EX(object).ptr)->function_table;
-                                                       EX(calling_namespace) = Z_OBJCE_P(EX(object).ptr);
                                                }
-                                               if (zend_hash_find(active_function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) {
+                                               if (zend_hash_find(EG(function_table), function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) {
                                                        zend_error(E_ERROR, "Call to undefined function:  %s()", function_name->value.str.val);
                                                }
-                                       } else { /* function pointer */
-                                               EX(object).ptr = NULL;
-                                               do {
-                                                       if (EG(namespace)) {
-                                                               if (zend_hash_find(&EG(namespace)->function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function) == SUCCESS) {
-                                                                       break;
-                                                               }
-                                                       }
-                                                       if (zend_hash_find(EG(function_table), function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) {
-                                                               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name->value.str.val);
-                                                       }
-                                                       EX(calling_namespace) = NULL;
-                                               } while (0);
-                                       }
+                                               EX(calling_namespace) = NULL;
+                                       } while (0);
                                        
                                        zval_dtor(&tmp);
                                        EX(fbc) = function;
-overloaded_function_call_cont:
-                                       FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
+
+                                       NEXT_OPCODE();
                                }
-                               NEXT_OPCODE();
                        case ZEND_DO_FCALL_BY_NAME:
                                EX(function_state).function = EX(fbc);
                                goto do_fcall_common;