]> granicus.if.org Git - php/commitdiff
Fix and generalize $this handling.
authorStanislav Malyshev <stas@php.net>
Wed, 16 Oct 2002 18:06:36 +0000 (18:06 +0000)
committerStanislav Malyshev <stas@php.net>
Wed, 16 Oct 2002 18:06:36 +0000 (18:06 +0000)
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

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

index cd6815e56ae6620ae711e453dd1dc6f0cc8164be..1777231fe2e094047d2c3172059c604beb8bb9b7 100644 (file)
@@ -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;
index 8fac9268d5f320a9f8c4f14471f96fa6100af724..ef045b0a61586ff6a3e53ed5e5ea537594805e5f 100644 (file)
@@ -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
index cf726acfad8d4ff4e5d782328f32c206dd0ac94b..b93c4cfefef79790f3b2e7528eb3d2adcc5ce7a4 100644 (file)
@@ -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);