diff options
author | Andi Gutmans <andi@php.net> | 2002-01-05 15:18:30 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2002-01-05 15:18:30 +0000 |
commit | a4248dd584812b78fefce6c44b3b9a6bff77f41d (patch) | |
tree | 2e39b3eb8a05ab4bcdab643736c1bb28fbf08e48 /Zend | |
parent | 62395159a92748d6ac96377f9e472b6bcb8363eb (diff) | |
download | php-git-a4248dd584812b78fefce6c44b3b9a6bff77f41d.tar.gz |
- Significantly improve the performance of method calls and $this->member
- lookups.
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend_compile.c | 27 | ||||
-rw-r--r-- | Zend/zend_compile.h | 1 | ||||
-rw-r--r-- | Zend/zend_execute.c | 49 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 35 | ||||
-rw-r--r-- | Zend/zend_globals.h | 2 |
5 files changed, 82 insertions, 32 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ed17a04d67..ca8dba8152 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 7d91ba6c4e..996300f629 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 482c105040..9f9cceb973 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 834ec351ee..43d2e7e1ec 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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; } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 38a1a69cbc..146c4ab09d 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -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; |