diff options
author | Stanislav Malyshev <stas@php.net> | 2002-10-16 18:06:36 +0000 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2002-10-16 18:06:36 +0000 |
commit | 349b3a096aa677b8ee3977a965b42c187b6a5bc5 (patch) | |
tree | d923e8bd2a51710e2ceb771737acaff96de92a53 | |
parent | 5ce6d653b8a9e335afec9d1250241ca78e71fa25 (diff) | |
download | php-git-349b3a096aa677b8ee3977a965b42c187b6a5bc5.tar.gz |
Fix and generalize $this handling.
ZEND_FETCH_FROM_THIS is removed, IS_UNUSED type on class variables will be
used instead as the sign that it's a fetch from $this
-rw-r--r-- | Zend/zend_compile.c | 51 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 66 |
3 files changed, 72 insertions, 47 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cd6815e56a..1777231fe2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1085,13 +1085,6 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) last_op->opcode = ZEND_INIT_METHOD_CALL; - if (last_op->op2.op_type == IS_UNUSED && last_op->op2.u.EA.type == ZEND_FETCH_FROM_THIS) { - last_op->op2 = last_op->op1; - memset(&last_op->op1, 0, sizeof(znode)); - SET_UNUSED(last_op->op1); - last_op->extended_value = ZEND_FETCH_FROM_THIS; - } - left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME; zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); @@ -2182,29 +2175,49 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS (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; - SET_UNUSED(opline_ptr->op2); - opline_ptr->op2.u.EA.type = ZEND_FETCH_FROM_THIS; + SET_UNUSED(opline_ptr->op1); /* this means $this for objects */ + opline_ptr->op2 = *property; + /* if it was usual fetch, we change it to object fetch */ + switch(opline_ptr->opcode) { + case ZEND_FETCH_W: + opline_ptr->opcode = ZEND_FETCH_OBJ_W; + break; + case ZEND_FETCH_R: + opline_ptr->opcode = ZEND_FETCH_OBJ_R; + break; + case ZEND_FETCH_RW: + opline_ptr->opcode = ZEND_FETCH_OBJ_RW; + break; + case ZEND_FETCH_IS: + opline_ptr->opcode = ZEND_FETCH_OBJ_IS; + break; + case ZEND_FETCH_UNSET: + opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET; + break; + case ZEND_FETCH_FUNC_ARG: + opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG; + break; + } if (CG(active_class_entry) && (opline_ptr->op1.op_type == IS_CONST)) { if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) { char *priv_name; int priv_name_length; - mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len); + mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len); - STR_FREE(opline_ptr->op1.u.constant.value.str.val); - opline_ptr->op1.u.constant.value.str.val = priv_name; - opline_ptr->op1.u.constant.value.str.len = priv_name_length; - } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) { + STR_FREE(opline_ptr->op2.u.constant.value.str.val); + opline_ptr->op2.u.constant.value.str.val = priv_name; + opline_ptr->op2.u.constant.value.str.len = priv_name_length; + } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) { char *prot_name; int prot_name_length; - mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len); + mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len); - STR_FREE(opline_ptr->op1.u.constant.value.str.val); - opline_ptr->op1.u.constant.value.str.val = prot_name; - opline_ptr->op1.u.constant.value.str.len = prot_name_length; + STR_FREE(opline_ptr->op2.u.constant.value.str.val); + opline_ptr->op2.u.constant.value.str.val = prot_name; + opline_ptr->op2.u.constant.value.str.len = prot_name_length; } } *result = opline_ptr->result; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8fac9268d5..ef045b0a61 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -204,7 +204,6 @@ typedef struct _zend_execute_data { #define IS_VAR (1<<2) #define IS_UNUSED (1<<3) /* Unused variable */ - #define EXT_TYPE_UNUSED (1<<0) #include "zend_globals.h" @@ -617,7 +616,6 @@ 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_FROM_THIS 4 /* class fetches */ #define ZEND_FETCH_CLASS_DEFAULT 0 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index cf726acfad..b93c4cfefe 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -252,6 +252,7 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z static inline void make_real_object(zval **object_ptr TSRMLS_DC) { +/* this should modify object only if it's empty */ if ((*object_ptr)->type == IS_NULL || ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0) || ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) { @@ -262,16 +263,42 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC) object_init(*object_ptr); } } - + +static inline zval **get_obj_zval_ptr_ptr(znode *op, temp_variable *Ts, int type TSRMLS_DC) +{ + if(op->op_type == IS_UNUSED) { + if(EG(This)) { + /* this should actually never be modified, _ptr_ptr is modified only when + the object is empty */ + return &EG(This); + } else { + zend_error(E_ERROR, "Using $this when not in object context"); + } + } + return get_zval_ptr_ptr(op, Ts, type); +} + +static inline zval *get_obj_zval_ptr(znode *op, temp_variable *Ts, int *freeop, int type TSRMLS_DC) +{ + if(op->op_type == IS_UNUSED) { + if(EG(This)) { + return EG(This); + } else { + zend_error(E_ERROR, "Using $this when not in object context"); + } + } + return get_zval_ptr(op, Ts, freeop, type); +} + static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); zval tmp; zval **retval = &Ts[result->u.var].var.ptr; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -301,9 +328,10 @@ static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, } /* here property is a string */ - PZVAL_UNLOCK(value); Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC); + + PZVAL_UNLOCK(value); if (property == &tmp) { zval_dtor(property); } @@ -608,13 +636,6 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari case ZEND_FETCH_STATIC_MEMBER: return Ts[opline->op2.u.var].EA.class_entry->static_members; break; - case ZEND_FETCH_FROM_THIS: - if (!EG(This)) { - zend_error(E_ERROR, "Using $this when not in object context"); - } - /* HACK!! 'this' should be always zend_object */ - return Z_OBJPROP_P(EG(This)); - break; EMPTY_SWITCH_DEFAULT_CASE() } return NULL; @@ -885,7 +906,7 @@ static void zend_fetch_dimension_address_from_tmp_var(znode *result, znode *op1, static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type TSRMLS_DC) { - zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type); + zval **container_ptr = get_obj_zval_ptr_ptr(op1, Ts, type); zval *container; zval ***retval = &Ts[result->u.var].var.ptr_ptr; @@ -895,7 +916,7 @@ static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, t SELECTIVE_PZVAL_LOCK(**retval, result); return; } - + /* this should modify object only if it's empty */ if (container->type == IS_NULL || (container->type == IS_BOOL && container->value.lval==0) || (container->type == IS_STRING && container->value.str.len == 0)) { @@ -942,7 +963,7 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o retval = &Ts[result->u.var].var.ptr; Ts[result->u.var].var.ptr_ptr = retval; - container = get_zval_ptr(op1, Ts, &EG(free_op1), type); + container = get_obj_zval_ptr(op1, Ts, &EG(free_op1), type); if (container == EG(error_zval_ptr)) { *retval = EG(error_zval_ptr); @@ -993,13 +1014,13 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); zval **retval = &Ts[result->u.var].var.ptr; int have_get_ptr = 0; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -1040,13 +1061,13 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); zval *retval = &Ts[result->u.var].tmp_var; int have_get_ptr = 0; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -1908,14 +1929,7 @@ binary_assign_op_addr_obj: EX(calling_scope) = EG(scope); - if (EX(opline)->extended_value == ZEND_FETCH_FROM_THIS) { - if (!EG(This)) { - zend_error(E_ERROR, "Can't fetch $this as not in object context"); - } - EX(object) = EG(This); - } else { - EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - } + EX(object) = get_obj_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); if (EX(object) && EX(object)->type == IS_OBJECT) { EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC); |