]> granicus.if.org Git - php/commitdiff
- Significantly improve the performance of method calls and $this->member
authorAndi Gutmans <andi@php.net>
Sat, 5 Jan 2002 15:18:30 +0000 (15:18 +0000)
committerAndi Gutmans <andi@php.net>
Sat, 5 Jan 2002 15:18:30 +0000 (15:18 +0000)
- lookups.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_globals.h

index ed17a04d67fede66f82c049564785383f6017894..ca8dba815283530a84d328445a6bc7a7158522e4 100644 (file)
@@ -917,6 +917,12 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
        }
 
        last_op->opcode = ZEND_INIT_METHOD_CALL;
+
+       if (last_op->extended_value == ZEND_FETCH_THIS) {
+               last_op->op2 = last_op->op1;            
+               memset(&last_op->op1, 0, sizeof(znode));
+       }
+
        zend_lowercase_znode_if_const(&last_op->op2);
 
        left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME;
@@ -1980,6 +1986,26 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
 {
        zend_op opline;
        zend_llist *fetch_list_ptr;
+       
+       zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
+
+       if (fetch_list_ptr->count == 1) {
+               zend_llist_element *le;
+               zend_op *opline_ptr;
+
+               le = fetch_list_ptr->head;
+               opline_ptr = (zend_op *) le->data;
+               if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
+                       (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) &&
+                       !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) {
+                       efree(opline_ptr->op1.u.constant.value.str.val);
+                       opline_ptr->op1 = *property;
+                       opline_ptr->extended_value = ZEND_FETCH_THIS;
+
+                       *result = opline_ptr->result;
+                       return;
+               }
+       }
 
        init_op(&opline TSRMLS_CC);
        opline.opcode = ZEND_FETCH_OBJ_W;       /* the backpatching routine assumes W */
@@ -1990,7 +2016,6 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
        opline.op2 = *property;
        *result = opline.result;
 
-       zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
        zend_llist_add_element(fetch_list_ptr, &opline);
 }
 
index 7d91ba6c4ec860baa5f127df67f393b80597c900..996300f6291c8e23429c2be595e532b4d1159984 100644 (file)
@@ -559,6 +559,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_FETCH_LOCAL                       1
 #define ZEND_FETCH_STATIC                      2
 #define ZEND_FETCH_STATIC_MEMBER       3
+#define ZEND_FETCH_THIS                                4
 
 /* class fetches */
 #define ZEND_FETCH_CLASS_DEFAULT       0
index 482c105040be6b15ae64790d1e30e62bd21a6c87..9f9cceb973ad40a71f3f14ed3cec60b6443e658a 100644 (file)
@@ -550,6 +550,12 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
                case ZEND_FETCH_STATIC_MEMBER:
                        target_symbol_table = Ts[opline->op2.u.var].EA.class_entry->static_members;
                        break;
+               case ZEND_FETCH_THIS:
+                       if (!EG(this)) {
+                               zend_error(E_ERROR, "Using $this when not in object context");
+                       }
+                       target_symbol_table = Z_OBJPROP_P(EG(this));
+                       break;
                EMPTY_SWITCH_DEFAULT_CASE()
        }
 
@@ -1595,7 +1601,14 @@ binary_assign_op_addr: {
                                        
                                        EX(calling_namespace) = EG(namespace);
 
-                                       EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                                       if (EX(opline)->extended_value == ZEND_FETCH_THIS) {
+                                               if (!EG(this)) {
+                                                       zend_error(E_ERROR, "Can't fetch $this as not in object context");
+                                               }
+                                               EX(object).ptr = EG(this);
+                                       } else {
+                                               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 */
 
@@ -1634,7 +1647,6 @@ binary_assign_op_addr: {
                                        zval *function_name;
                                        zend_function *function;
                                        zval tmp;
-                                       zval **object_ptr_ptr;
                                        zend_class_entry *ce;
                                        zend_bool is_const;
                                        char *function_name_strval;
@@ -1662,14 +1674,10 @@ binary_assign_op_addr: {
                                        
                                        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 */
+                                       if (EX(object).ptr = EG(this)) {
+                                               EX(object).ptr->refcount++;
                                        }
+
                                        ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
 
                                        EX(calling_namespace) = ce;
@@ -1764,21 +1772,22 @@ do_fcall_common:
                                {
                                        zval **original_return_value;
                                        zend_class_entry *current_namespace;
+                                       zval *current_this;
                                        int return_value_used = RETURN_VALUE_USED(EX(opline));
 
                                        zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) EX(opline)->extended_value, NULL);
                                        current_namespace = EG(namespace);
                                        EG(namespace) = EX(calling_namespace);
 
+                                       current_this = EG(this);
+                                       EG(this) = EX(object).ptr;
+
                                        EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
 
                                        if (EX(function_state).function->type==ZEND_INTERNAL_FUNCTION) {        
                                                ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
                                                INIT_ZVAL(*(EX(Ts)[EX(opline)->result.u.var].var.ptr));
                                                ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, return_value_used TSRMLS_CC);
-                                               if (EX(object).ptr) {
-                                                       zval_ptr_dtor(&EX(object).ptr);
-                                               }
                                                EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref = 0;
                                                EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount = 1;
                                                if (!return_value_used) {
@@ -1798,16 +1807,6 @@ do_fcall_common:
                                                }
                                                calling_symbol_table = EG(active_symbol_table);
                                                EG(active_symbol_table) = EX(function_state).function_symbol_table;
-                                               if (EX(opline)->opcode==ZEND_DO_FCALL_BY_NAME
-                                                       && EX(object).ptr
-                                                       && EX(fbc)->type!=ZEND_OVERLOADED_FUNCTION) {
-                                                       zval **this_ptr;
-                                                       zval *null_ptr = NULL;
-
-                                                       zend_hash_update(EX(function_state).function_symbol_table, "this", sizeof("this"), &null_ptr, sizeof(zval *), (void **) &this_ptr);
-                                                       *this_ptr = EX(object).ptr;
-                                                       EX(object).ptr = NULL;
-                                               }
                                                original_return_value = EG(return_value_ptr_ptr);
                                                EG(return_value_ptr_ptr) = EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr;
                                                EG(active_op_array) = (zend_op_array *) EX(function_state).function;
@@ -1854,6 +1853,12 @@ do_fcall_common:
 
                                        EG(namespace) = current_namespace;
 
+                                       if (EG(this)) {
+                                               zval_ptr_dtor(&EG(this));
+                                       }
+
+                                       EG(this) = current_this;
+                                       
                                        if (EG(exception)) {
                                                if (EX(opline)->op2.u.opline_num == -1) {
                                                        RETURN_FROM_EXECUTE_LOOP(execute_data);
index 834ec351eef1fb8551a527052d8f871e8a7f16e4..43d2e7e1ecd873bffed50c49e0afd95c902f128d 100644 (file)
@@ -164,6 +164,7 @@ void init_executor(TSRMLS_D)
        EG(main_class_ptr) = &CG(main_class);
        CG(main_class).static_members = &EG(symbol_table);
 
+       EG(this) = NULL;
 }
 
 
@@ -442,6 +443,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
        zval function_name_copy;
        zend_class_entry *current_namespace;
        zend_class_entry *calling_namespace = NULL;
+       zval *current_this;
 
        *retval_ptr_ptr = NULL;
 
@@ -542,6 +544,24 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
        current_namespace = EG(namespace);
        EG(namespace) = calling_namespace;
 
+       current_this = EG(this);
+       EG(this) = *object_pp;
+
+       if (EG(this)) {
+               if (!PZVAL_IS_REF(EG(this))) {
+                       EG(this)->refcount++; /* For $this pointer */
+               } else {
+                       zval *this_ptr;
+
+                       ALLOC_ZVAL(this_ptr);
+                       *this_ptr = *EG(this);
+                       INIT_PZVAL(this_ptr);
+                       zval_copy_ctor(this_ptr);
+                       EG(this) = this_ptr;
+               }
+       }
+
+
        if (function_state.function->type == ZEND_USER_FUNCTION) {
                calling_symbol_table = EG(active_symbol_table);
                if (symbol_table) {
@@ -550,14 +570,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
                        ALLOC_HASHTABLE(EG(active_symbol_table));
                        zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
                }
-               if (object_pp) {
-                       zval *dummy, **this_ptr;
-                               
-                       ALLOC_ZVAL(dummy);
-                       INIT_ZVAL(*dummy);      
-                       zend_hash_update(EG(active_symbol_table), "this", sizeof("this"), &dummy, sizeof(zval *), (void **) &this_ptr);
-                       zend_assign_to_variable_reference(NULL, this_ptr, object_pp, NULL TSRMLS_CC);
-               }
+
                original_return_value = EG(return_value_ptr_ptr);
                original_op_array = EG(active_op_array);
                EG(return_value_ptr_ptr) = retval_ptr_ptr;
@@ -588,8 +601,12 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
        zend_ptr_stack_clear_multiple(TSRMLS_C);
        EG(function_state_ptr) = original_function_state_ptr;
 
+       if (EG(this)) {
+               zval_ptr_dtor(&EG(this));
+       }
        EG(namespace) = current_namespace;
-
+       EG(this) = current_this;
+       
        return SUCCESS;
 }
 
index 38a1a69cbc1b60e5bff4a00ead811ad4ebe300ac..146c4ab09dfb4508762501d943061321f5ad081c 100644 (file)
@@ -159,6 +159,8 @@ struct _zend_executor_globals {
        zend_class_entry *namespace;
        zend_class_entry *main_class_ptr;
 
+       zval *this;
+
        long precision;
 
        int ticks_count;