From: Stanislav Malyshev Date: Sun, 10 Mar 2002 13:42:37 +0000 (+0000) Subject: New stuff for objects API: X-Git-Tag: help~106 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04ed2b520f83f04ba9aa752bb3953bd825821b77;p=php New stuff for objects API: - Better assignment handling - More flexible operations with zval-containing objects --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 997848d350..b5943c1464 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 4b00f5727b..1a24312e4c 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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 */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4c9dea3cb5..2a44352254 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -39,10 +39,14 @@ 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); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 9db2cbce5a..a2a7a5665c 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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 */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 21140956ca..f264187c9a 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -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;