summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>2002-01-05 15:18:30 +0000
committerAndi Gutmans <andi@php.net>2002-01-05 15:18:30 +0000
commita4248dd584812b78fefce6c44b3b9a6bff77f41d (patch)
tree2e39b3eb8a05ab4bcdab643736c1bb28fbf08e48 /Zend
parent62395159a92748d6ac96377f9e472b6bcb8363eb (diff)
downloadphp-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.c27
-rw-r--r--Zend/zend_compile.h1
-rw-r--r--Zend/zend_execute.c49
-rw-r--r--Zend/zend_execute_API.c35
-rw-r--r--Zend/zend_globals.h2
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;