]> granicus.if.org Git - php/commitdiff
New stuff for objects API:
authorStanislav Malyshev <stas@php.net>
Sun, 10 Mar 2002 13:42:37 +0000 (13:42 +0000)
committerStanislav Malyshev <stas@php.net>
Sun, 10 Mar 2002 13:42:37 +0000 (13:42 +0000)
- Better assignment handling
- More flexible operations with zval-containing objects

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

index 997848d350272beb8ceae4a2b05f9d3fe660bb1e..b5943c1464d1f40de6892cf3820656d0bdf58bde 100644 (file)
@@ -181,17 +181,85 @@ void zend_do_unary_op(int op, znode *result, znode *op1 TSRMLS_DC)
        SET_UNUSED(opline->op2);
 }
 
+#define MAKE_NOP(opline)       { opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED;  }
+
+static void zend_replace_object_fetch(zend_op *last_op, znode *value TSRMLS_DC)
+{
+       if(value->op_type != IS_VAR) {
+               last_op->opcode = ZEND_MAKE_VAR;
+               last_op->result.op_type = IS_VAR;
+               last_op->result.u.EA.type = 0;
+               last_op->result.u.var = get_temporary_variable(CG(active_op_array));
+               last_op->op1 = *value;
+               SET_UNUSED(last_op->op2);
+               value->op_type = IS_VAR;
+               value->u.EA.type = 0;
+               value->u.var = last_op->result.u.var;
+       } else {
+               MAKE_NOP(last_op);
+       }
+}
 
 void zend_do_binary_assign_op(int op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
 {
+       int last_op_number = get_next_op_number(CG(active_op_array))-1;
+       zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = op;
+       if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+               
+               switch(op) {
+                       case ZEND_ASSIGN_ADD:
+                               opline->opcode = ZEND_ASSIGN_ADD_OBJ;
+                               break;
+                       case ZEND_ASSIGN_SUB:
+                               opline->opcode = ZEND_ASSIGN_SUB_OBJ;
+                               break;
+                       case ZEND_ASSIGN_MUL:
+                               opline->opcode = ZEND_ASSIGN_MUL_OBJ;
+                               break;
+                       case ZEND_ASSIGN_DIV:
+                               opline->opcode = ZEND_ASSIGN_DIV_OBJ;
+                               break;
+                       case ZEND_ASSIGN_MOD:
+                               opline->opcode = ZEND_ASSIGN_MOD_OBJ;
+                               break;
+                       case ZEND_ASSIGN_SL:
+                               opline->opcode = ZEND_ASSIGN_SL_OBJ;
+                               break;
+                       case ZEND_ASSIGN_SR:
+                               opline->opcode = ZEND_ASSIGN_SR_OBJ;
+                               break;
+                       case ZEND_ASSIGN_CONCAT:
+                               opline->opcode = ZEND_ASSIGN_CONCAT_OBJ;
+                               break;
+                       case ZEND_ASSIGN_BW_OR:
+                               opline->opcode = ZEND_ASSIGN_BW_OR_OBJ;
+                               break;
+                       case ZEND_ASSIGN_BW_AND:
+                               opline->opcode = ZEND_ASSIGN_BW_AND_OBJ;
+                               break;
+                       case ZEND_ASSIGN_BW_XOR:
+                               opline->opcode = ZEND_ASSIGN_BW_XOR_OBJ;
+                               break;
+                       default:
+                               zend_error(E_ERROR, "Unknown binary op opcode %d", op);
+               }
+               
+               opline->op2 = last_op->op2;
+               opline->op1 = last_op->op1;
+               zend_replace_object_fetch(last_op, op2 TSRMLS_CC);
+               opline->extended_value = op2->u.var;
+               
+       } else {
+               opline->opcode = op;
+               opline->op1 = *op1;
+               opline->op2 = *op2;
+       }
+
        opline->result.op_type = IS_VAR;
        opline->result.u.EA.type = 0;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *op1;
-       opline->op2 = *op2;
        *result = opline->result;
 }
 
@@ -316,14 +384,26 @@ void zend_do_echo(znode *arg TSRMLS_DC)
 
 void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
 {
+       int last_op_number = get_next_op_number(CG(active_op_array))-1;
+       zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = ZEND_ASSIGN;
+       if(last_op->opcode == ZEND_FETCH_OBJ_W) {
+               opline->opcode = ZEND_ASSIGN_OBJ;
+               opline->op1 = last_op->op1;
+               opline->op2 = last_op->op2;
+               
+               zend_replace_object_fetch(last_op, value TSRMLS_CC);
+
+               opline->extended_value = value->u.var;
+       } else {
+               opline->opcode = ZEND_ASSIGN;
+               opline->op1 = *variable;
+               opline->op2 = *value;
+       }
        opline->result.op_type = IS_VAR;
        opline->result.u.EA.type = 0;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *variable;
-       opline->op2 = *value;
        *result = opline->result;
 }
 
@@ -447,28 +527,49 @@ void zend_do_for_end(znode *second_semicolon_token TSRMLS_DC)
 
 void zend_do_pre_incdec(znode *result, znode *op1, int op TSRMLS_DC)
 {
+       int last_op_number = get_next_op_number(CG(active_op_array))-1;
+       zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = op;
+       if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+               opline->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
+               opline->op1 = last_op->op1;
+               opline->op2 = last_op->op2;
+               
+               MAKE_NOP(last_op);
+       } else {
+               opline->opcode = op;
+               opline->op1 = *op1;
+               SET_UNUSED(opline->op2);
+       }
+
        opline->result.op_type = IS_VAR;
        opline->result.u.EA.type = 0;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *op1;
        *result = opline->result;
-       SET_UNUSED(opline->op2);
 }
 
 
 void zend_do_post_incdec(znode *result, znode *op1, int op TSRMLS_DC)
 {
+       int last_op_number = get_next_op_number(CG(active_op_array))-1;
+       zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = op;
+       if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+               opline->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
+               opline->op1 = last_op->op1;
+               opline->op2 = last_op->op2;
+               
+               MAKE_NOP(last_op);
+       } else {
+               opline->opcode = op;
+               opline->op1 = *op1;
+               SET_UNUSED(opline->op2);
+       }
        opline->result.op_type = IS_TMP_VAR;
        opline->result.u.var = get_temporary_variable(CG(active_op_array));
-       opline->op1 = *op1;
        *result = opline->result;
-       SET_UNUSED(opline->op2);
 }
 
 
index 4b00f5727bf6278a153a1f0a560b7b5c53e6add8..1a24312e4caa64e1e9dd13e14ebc3877e78d3119 100644 (file)
@@ -559,6 +559,25 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define        ZEND_IMPORT_CLASS                       117
 #define        ZEND_IMPORT_CONST                       118
 
+#define ZEND_ASSIGN_ADD_OBJ                    121
+#define ZEND_ASSIGN_SUB_OBJ                    122
+#define ZEND_ASSIGN_MUL_OBJ                    123
+#define ZEND_ASSIGN_DIV_OBJ                    124
+#define ZEND_ASSIGN_MOD_OBJ                    125
+#define ZEND_ASSIGN_SL_OBJ                     126
+#define ZEND_ASSIGN_SR_OBJ                     127
+#define ZEND_ASSIGN_CONCAT_OBJ         128
+#define ZEND_ASSIGN_BW_OR_OBJ          129
+#define ZEND_ASSIGN_BW_AND_OBJ         130
+#define ZEND_ASSIGN_BW_XOR_OBJ         131
+                                                                       
+#define ZEND_PRE_INC_OBJ                       132
+#define ZEND_PRE_DEC_OBJ                       133
+#define ZEND_POST_INC_OBJ                      134
+#define ZEND_POST_DEC_OBJ                      135
+                                                                       
+#define ZEND_ASSIGN_OBJ                                136
+#define ZEND_MAKE_VAR                          137
 /* end of block */
 
 
index 4c9dea3cb5751125c8e48241720e4b2455a3fe76..2a4435225461d9d93c644cc43c4b1d48dc9c275d 100644 (file)
        switch (opcode) { \
                case ZEND_PRE_INC: \
                case ZEND_POST_INC: \
+               case ZEND_PRE_INC_OBJ: \
+               case ZEND_POST_INC_OBJ: \
                        (op) = increment_function; \
                        break; \
                case ZEND_PRE_DEC: \
                case ZEND_POST_DEC: \
+               case ZEND_PRE_DEC_OBJ: \
+               case ZEND_POST_DEC_OBJ: \
                        (op) = decrement_function; \
                        break; \
                default: \
@@ -184,7 +188,12 @@ static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2,
                        break;
        }
 
-       retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC);
+       if(Z_OBJ_HT_P(object)->get_property_ptr != NULL) {
+               retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC);
+       } else {
+               zend_error(E_WARNING, "This object doesn't support property references");
+               retval = &EG(error_zval_ptr);
+       }
        
        if (prop_ptr == &tmp) {
                zval_dtor(prop_ptr);
@@ -268,6 +277,134 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z
        }
 }
 
+static inline void make_real_object(zval **object_ptr) {
+       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)) {
+               if (!PZVAL_IS_REF(*object_ptr)) {
+                       SEPARATE_ZVAL(object_ptr);
+               }
+               zend_error(E_NOTICE, "Creating default object from empty value");
+               object_init(*object_ptr);
+       }
+}
+       
+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;
+       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);
+       object = *object_ptr;
+       
+       if (object->type != IS_OBJECT) {
+               zend_error(E_WARNING, "Attempt to assign property of non-object");
+               FREE_OP(Ts, op2, EG(free_op2));
+               *retval = EG(uninitialized_zval_ptr);
+
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+               return;
+       }
+       
+       /* here we are sure we are dealing with an object */
+       switch (op2->op_type) {
+               case IS_CONST:
+                       /* already a constant string */
+                       break;
+               case IS_VAR:
+                       tmp = *property;
+                       zval_copy_ctor(&tmp);
+                       convert_to_string(&tmp);
+                       property = &tmp;
+                       break;
+               case IS_TMP_VAR:
+                       convert_to_string(property);
+                       break;
+       }
+
+       /* here property is a string */
+       PZVAL_UNLOCK(value);
+       
+       Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
+       if (property == &tmp) {
+               zval_dtor(property);
+       }
+       
+       FREE_OP(Ts, op2, EG(free_op2));
+       if (result) {
+               Ts[result->u.var].var.ptr = value;
+               Ts[result->u.var].var.ptr_ptr = NULL; /* see if we can nuke this */
+               SELECTIVE_PZVAL_LOCK(value, result);
+       }
+}
+
+static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) TSRMLS_DC) {
+       zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+       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;
+
+       Ts[result->u.var].var.ptr_ptr = NULL;
+       make_real_object(object_ptr);
+       object = *object_ptr;
+       
+       if (object->type != IS_OBJECT) {
+               zend_error(E_WARNING, "Attempt to assign property of non-object");
+               FREE_OP(Ts, op2, EG(free_op2));
+               *retval = EG(uninitialized_zval_ptr);
+
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+               return;
+       }
+       
+       /* here we are sure we are dealing with an object */
+       switch (op2->op_type) {
+               case IS_CONST:
+                       /* already a constant string */
+                       break;
+               case IS_VAR:
+                       tmp = *property;
+                       zval_copy_ctor(&tmp);
+                       convert_to_string(&tmp);
+                       property = &tmp;
+                       break;
+               case IS_TMP_VAR:
+                       convert_to_string(property);
+                       break;
+       }
+
+       /* here property is a string */
+       PZVAL_UNLOCK(value);
+       
+       if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
+               zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(zptr);
+
+               binary_op(*zptr, *zptr, value);
+               *retval = *zptr;
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+       } else {
+               zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(&z);
+               binary_op(z, z, value);
+               Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+               *retval = z;
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+               if(z->refcount <= 1) {
+                       zval_dtor(z);
+               }
+       }
+
+       if (property == &tmp) {
+               zval_dtor(property);
+       }
+       
+       FREE_OP(Ts, op2, EG(free_op2));
+}
 
 static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2, zval *value, int type, temp_variable *Ts TSRMLS_DC)
 {
@@ -884,6 +1021,89 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o
        return;
 }
 
+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;
+       zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+       zval **retval = &Ts[result->u.var].var.ptr;
+
+       make_real_object(object_ptr);
+       object = *object_ptr;
+       
+       if (object->type != IS_OBJECT) {
+               zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+               FREE_OP(Ts, op2, EG(free_op2));
+               *retval = EG(uninitialized_zval_ptr);
+
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+               return;
+       }
+       
+       /* here we are sure we are dealing with an object */
+
+       if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
+               zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(zptr);
+
+               incdec_op(*zptr);
+               *retval = *zptr;
+               SELECTIVE_PZVAL_LOCK(*retval, result);
+       } else {
+               zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(&z);
+               incdec_op(z);
+               Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+               if(z->refcount <= 1) {
+                       zval_dtor(z);
+               }
+       }
+       
+       FREE_OP(Ts, op2, EG(free_op2));
+}
+
+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;
+       zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+       zval *retval = &Ts[result->u.var].tmp_var;
+
+       make_real_object(object_ptr);
+       object = *object_ptr;
+       
+       if (object->type != IS_OBJECT) {
+               zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+               FREE_OP(Ts, op2, EG(free_op2));
+               *retval = *EG(uninitialized_zval_ptr);
+               return;
+       }
+       
+       /* here we are sure we are dealing with an object */
+
+       if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
+               zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(zptr);
+
+               *retval = **zptr;
+               zendi_zval_copy_ctor(*retval);
+
+               incdec_op(*zptr);
+       } else {
+               zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
+               SEPARATE_ZVAL_IF_NOT_REF(&z);
+               *retval = *z;
+               zendi_zval_copy_ctor(*retval);
+               incdec_op(z);
+               Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+               if(z->refcount <= 1) {
+                       zval_dtor(z);
+               }
+       }
+       
+       FREE_OP(Ts, op2, EG(free_op2));
+}
+
 
 #if ZEND_INTENSIVE_DEBUGGING
 
@@ -1102,6 +1322,59 @@ binary_assign_op_addr: {
                                        AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var);
                                }
                                NEXT_OPCODE();
+
+                       case ZEND_ASSIGN_ADD_OBJ:
+                               EG(binary_op) = add_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_SUB_OBJ:
+                               EG(binary_op) = sub_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_MUL_OBJ:
+                               EG(binary_op) = mul_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_DIV_OBJ:
+                               EG(binary_op) = div_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_MOD_OBJ:
+                               EG(binary_op) = mod_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_SL_OBJ:
+                               EG(binary_op) = shift_left_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_SR_OBJ:
+                               EG(binary_op) = shift_right_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_CONCAT_OBJ:
+                               EG(binary_op) = concat_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_BW_OR_OBJ:
+                               EG(binary_op) = bitwise_or_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_BW_AND_OBJ:
+                               EG(binary_op) = bitwise_and_function;
+                               goto binary_assign_op_addr_obj;
+                       case ZEND_ASSIGN_BW_XOR_OBJ:
+                               EG(binary_op) = bitwise_xor_function;
+                               /* Fall through */
+binary_assign_op_addr_obj:
+                               zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts), EG(binary_op) TSRMLS_CC);
+                               NEXT_OPCODE();
+                       case ZEND_PRE_INC_OBJ:
+                       case ZEND_PRE_DEC_OBJ: {
+                               int (*incdec_op)(zval *op);
+
+                               get_incdec_op(incdec_op, EX(opline)->opcode);
+                               zend_pre_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC);
+                       }
+                       NEXT_OPCODE();
+                       case ZEND_POST_INC_OBJ:
+                       case ZEND_POST_DEC_OBJ: {
+                               int (*incdec_op)(zval *op);
+
+                               get_incdec_op(incdec_op, EX(opline)->opcode);
+                               zend_post_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC);
+                       }
+                       NEXT_OPCODE();
                        case ZEND_PRE_INC:
                        case ZEND_PRE_DEC:
                        case ZEND_POST_INC:
@@ -1261,6 +1534,35 @@ binary_assign_op_addr: {
                                zend_fetch_dimension_address_from_tmp_var(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts) TSRMLS_CC);
                                AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var);
                                NEXT_OPCODE();
+                       case ZEND_MAKE_VAR: {
+                               zval *value, *value2;
+
+                               value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+                               switch(EX(opline)->op1.op_type) {
+                                       case IS_TMP_VAR:
+                                               value2 = value;
+                                               ALLOC_ZVAL(value);
+                                               *value = *value2;
+                                               value->is_ref = 0;
+                                               value->refcount = 0; /* lock will increase this */
+                                               break;
+                                       case IS_CONST:
+                                               value2 = value;
+                                               ALLOC_ZVAL(value);
+                                               *value = *value2;
+                                               zval_copy_ctor(value);
+                                               value->is_ref = 0;
+                                               value->refcount = 0; /* lock will increase this */
+                                               break;
+                               }
+                               
+                               EX(Ts)[EX(opline)->result.u.var].var.ptr = value;
+                               PZVAL_LOCK(EX(Ts)[EX(opline)->result.u.var].var.ptr);
+                       }
+                       NEXT_OPCODE();
+                       case ZEND_ASSIGN_OBJ:
+                               zend_assign_to_object(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts) TSRMLS_CC);
+                               NEXT_OPCODE();
                        case ZEND_ASSIGN: {
                                        zval *value;
                                        value = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
index 9db2cbce5a99aa33ad7e312537d117bf69084066..a2a7a5665c7ef736a9723c2c43af4f404975bf2e 100644 (file)
@@ -65,7 +65,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
 {
        zend_object *zobj;
        zval tmp_member;
-       zval *variable_ptr;
+       zval **variable_ptr;
        
        zobj = Z_GET_OBJ(object);
 
@@ -77,19 +77,20 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
        }
 
        if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member), (void **) &variable_ptr) == SUCCESS) {
-               if (variable_ptr == EG(error_zval_ptr) || member == EG(error_zval_ptr)) {
+               if (*variable_ptr == EG(error_zval_ptr) || member == EG(error_zval_ptr)) {
                        /* variable_ptr = EG(uninitialized_zval_ptr); */
 /*     } else if (variable_ptr==&EG(uninitialized_zval) || variable_ptr!=value_ptr) { */
-               } else if (variable_ptr != value) {
-                       variable_ptr->refcount--;
-                       if (variable_ptr->refcount == 0) {
-                               zendi_zval_dtor(*variable_ptr);
-                               FREE_ZVAL(variable_ptr);
+               } else if (*variable_ptr != value) {
+                       (*variable_ptr)->refcount--;
+                       if ((*variable_ptr)->refcount == 0) {
+                               zendi_zval_dtor(**variable_ptr);
+                               FREE_ZVAL(*variable_ptr);
                        }
                }
        }
 
-       zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL); 
+       value->refcount++;
+       zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL);
        if (member == &tmp_member) {
                zval_dtor(member);
        }
@@ -117,7 +118,7 @@ static zval **zend_std_get_property_ptr(zval *object, zval *member TSRMLS_DC)
        if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) {
                zval *new_zval = &EG(uninitialized_zval);
 
-               // zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member));
+               zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member));
                new_zval->refcount++;
                zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval);
        }
@@ -243,6 +244,7 @@ zend_object_handlers std_object_handlers = {
        zend_std_read_property,                  /* read_property */
        zend_std_write_property,                 /* write_property */
        zend_std_get_property_ptr,               /* get_property_ptr */
+       zend_std_get_property_ptr,               /* get_property_zval_ptr */
        NULL,                                    /* get */
        NULL,                                    /* set */
        zend_std_has_property,                   /* has_property */
index 21140956caa2def4bd2681acf9b7fb9367ec2272..f264187c9aacc4480deb49cb5ca9ffca6d32915e 100644 (file)
@@ -9,7 +9,9 @@ typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *v
 /* Used to set property of the object */
 
 typedef zval **(*zend_object_get_property_ptr_t)(zval *object, zval *member TSRMLS_DC);
-/* Used to create pointer to the property of the object, for future r/w access */
+/* Used to create pointer to the property of the object, for future r/w access via get/set */
+typedef zval **(*zend_object_get_property_zval_ptr_t)(zval *object, zval *member TSRMLS_DC);
+/* Used to create pointer to the property of the object, for future direct r/w access */
 typedef void (*zend_object_set_t)(zval **property, zval *value TSRMLS_DC);
 /* Used to set object value (most probably used in combination with
 typedef the result of the get_property_ptr) */
@@ -54,6 +56,7 @@ typedef struct _zend_object_handlers {
        zend_object_read_property_t              read_property;
        zend_object_write_property_t             write_property;
        zend_object_get_property_ptr_t           get_property_ptr;
+       zend_object_get_property_zval_ptr_t      get_property_zval_ptr;
        zend_object_get_t                        get;
        zend_object_set_t                        set;
        zend_object_has_property_t               has_property;