From: Andi Gutmans Date: Tue, 7 Aug 2001 03:17:33 +0000 (+0000) Subject: - Sync Engine2 CVS with latest Engine CVS X-Git-Tag: BEFORE_PARAM_PARSING_CHANGE~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5af7770a816fd74331afdee06e61acea184ac87d;p=php - Sync Engine2 CVS with latest Engine CVS --- diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 699601644d..0929f815df 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -212,6 +212,10 @@ SOURCE=.\zend_llist.c # End Source File # Begin Source File +SOURCE=.\zend_objects.c +# End Source File +# Begin Source File + SOURCE=.\zend_opcode.c # End Source File # Begin Source File @@ -352,6 +356,10 @@ SOURCE=.\zend_modules.h # End Source File # Begin Source File +SOURCE=.\zend_objects.h +# End Source File +# Begin Source File + SOURCE=.\zend_operators.h # End Source File # Begin Source File diff --git a/Zend/zend.h b/Zend/zend.h index 5273a92b53..090ae3c829 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -175,6 +175,29 @@ typedef struct _zend_object { HashTable *properties; } zend_object; +typedef unsigned int zend_object_handle; + +typedef zend_object *(*get_address_t)(zend_object_handle handle); /* Don't return zval ** so that we can't change it */ +typedef zval **(*get_property_address_t)(zend_object_handle handle, zval *offset, int type); +typedef void (*add_ref_t)(zend_object_handle handle); +typedef void (*del_ref_t)(zend_object_handle handle); +typedef void (*delete_obj_t)(zend_object_handle handle); + +typedef struct _zend_object_handlers { + get_address_t get_address; + get_property_address_t get_property_address; + add_ref_t add_ref; + del_ref_t del_ref; + delete_obj_t delete_obj; +} zend_object_handlers; + +typedef struct _zend_object_value { + zend_object_handle handle; + zend_object_handlers handlers; +} zend_object_value; + +#include "zend_objects.h" + typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ @@ -183,7 +206,12 @@ typedef union _zvalue_value { int len; } str; HashTable *ht; /* hash table value */ - zend_object obj; +/* struct { + zend_class_entry *ce; + HashTable *properties; + } obj; +*/ + zend_object_value obj; } zvalue_value; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 08aaeeb528..1cf03a147c 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -211,7 +211,6 @@ static int zend_check_class(zval *obj, zend_class_entry *expected_ce) return 1; } } - return 0; } @@ -569,17 +568,21 @@ ZEND_API int _array_init(zval *arg ZEND_FILE_LINE_DC) ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) { zval *tmp; + zend_object *object; if (!class_type->constants_updated) { zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); class_type->constants_updated = 1; } - ALLOC_HASHTABLE_REL(arg->value.obj.properties); - zend_hash_init(arg->value.obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(arg->value.obj.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + arg->value.obj = zend_objects_new(&object); + + ALLOC_HASHTABLE_REL(object->properties); + zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + object->ce = class_type; + arg->type = IS_OBJECT; - arg->value.obj.ce = class_type; return SUCCESS; } @@ -943,7 +946,7 @@ ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n MAKE_STD_ZVAL(tmp); ZVAL_RESOURCE(tmp, n); - + return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } @@ -954,7 +957,7 @@ ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d MAKE_STD_ZVAL(tmp); ZVAL_DOUBLE(tmp, d); - + return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5422bff2ad..b34e6ff93a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -704,7 +704,6 @@ void zend_do_free(znode *op1 TSRMLS_DC) } } - void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference TSRMLS_DC) { zend_op_array op_array; @@ -2022,7 +2021,7 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va } -void zend_do_unset(znode *variable TSRMLS_DC) +void zend_do_unset(znode *variable, int type TSRMLS_DC) { zend_op *last_op; @@ -2038,6 +2037,7 @@ void zend_do_unset(znode *variable TSRMLS_DC) break; } + last_op->extended_value = type; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index fda7b57239..3fd85e527a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -329,7 +329,7 @@ void zend_do_new_list_end(TSRMLS_D); void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC); void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC); -void zend_do_unset(znode *variable TSRMLS_DC); +void zend_do_unset(znode *variable, int type TSRMLS_DC); void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC); void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC); @@ -537,6 +537,10 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_LOCAL 1 #define ZEND_FETCH_STATIC 2 +/* unset types */ +#define ZEND_UNSET_REG 0 +#define ZEND_UNSET_OBJ 1 + /* var status for backpatching */ #define BP_VAR_R 0 #define BP_VAR_W 1 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ec82e104a8..ba96d242be 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1497,7 +1497,7 @@ binary_assign_op_addr: { object.ptr = _get_object_zval_ptr(&opline->op1, Ts, &EG(free_op1) TSRMLS_CC); if ((!object.ptr && Ts[opline->op1.u.var].EA.type==IS_OVERLOADED_OBJECT) - || ((object.ptr && object.ptr->type==IS_OBJECT) && (object.ptr->value.obj.ce->handle_function_call))) { /* overloaded function call */ + || ((object.ptr && object.ptr->type==IS_OBJECT) && Z_OBJCE_P(object.ptr)->handle_function_call)) { /* overloaded function call */ zend_overloaded_element overloaded_element; overloaded_element.element = *function_name; @@ -1517,15 +1517,22 @@ binary_assign_op_addr: { goto overloaded_function_call_cont; } - if (!object.ptr || object.ptr->type != IS_OBJECT) { + if (object.ptr && object.ptr->type == IS_OBJECT) { + active_function_table = &Z_OBJCE_P(object.ptr)->function_table; + } else { zend_error(E_ERROR, "Call to a member function on a non-object"); } - if (!object.ptr->is_ref && object.ptr->refcount > 1) { - zend_error(E_ERROR, "Bug: Problem in method call\n"); + if (!PZVAL_IS_REF(object.ptr)) { + object.ptr->refcount++; /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + *this_ptr = *object.ptr; + INIT_PZVAL(this_ptr); + zval_copy_ctor(this_ptr); + object.ptr = this_ptr; } - object.ptr->is_ref=1; - object.ptr->refcount++; /* For $this pointer */ - active_function_table = &(object.ptr->value.obj.ce->function_table); + active_function_table = &Z_OBJCE_P(object.ptr)->function_table; } } else { /* function pointer */ object.ptr = NULL; @@ -1568,7 +1575,7 @@ do_fcall_common: INIT_ZVAL(*(Ts[opline->result.u.var].var.ptr)); ((zend_internal_function *) function_state.function)->handler(opline->extended_value, Ts[opline->result.u.var].var.ptr, object.ptr, return_value_used TSRMLS_CC); if (object.ptr) { - object.ptr->refcount--; + zval_ptr_dtor(&object.ptr); } Ts[opline->result.u.var].var.ptr->is_ref = 0; Ts[opline->result.u.var].var.ptr->refcount = 1; @@ -1596,9 +1603,6 @@ do_fcall_common: zval *null_ptr = NULL; zend_hash_update(function_state.function_symbol_table, "this", sizeof("this"), &null_ptr, sizeof(zval *), (void **) &this_ptr); - if (!PZVAL_IS_REF(object.ptr)) { - zend_error(E_WARNING, "Problem with method call - please report this bug"); - } *this_ptr = object.ptr; object.ptr = NULL; } @@ -2142,6 +2146,8 @@ send_by_ref: NEXT_OPCODE(); case ZEND_UNSET_VAR: { zval tmp, *variable = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + zval **object; + zend_bool unset_object; if (variable->type != IS_STRING) { tmp = *variable; @@ -2150,6 +2156,18 @@ send_by_ref: variable = &tmp; } + unset_object = (opline->extended_value == ZEND_UNSET_OBJ); + + if (unset_object) { + if (zend_hash_find(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1, (void **)&object) == FAILURE) { + zend_error(E_ERROR, "Cannot delete non-existing object"); + } + if (Z_TYPE_PP(object) != IS_OBJECT) { + zend_error(E_ERROR, "Cannot call delete on non-object type"); + } + (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle); + } + zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1); if (variable == &tmp) { @@ -2161,7 +2179,11 @@ send_by_ref: case ZEND_UNSET_DIM_OBJ: { zval **container = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R); zval *offset = get_zval_ptr(&opline->op2, Ts, &EG(free_op2), BP_VAR_R); + zend_bool unset_object; + zval **object; + unset_object = (opline->extended_value == ZEND_UNSET_OBJ); + if (container) { HashTable *ht; @@ -2170,7 +2192,7 @@ send_by_ref: ht = (*container)->value.ht; break; case IS_OBJECT: - ht = (*container)->value.obj.properties; + ht = Z_OBJPROP_PP(container); break; default: ht = NULL; @@ -2190,13 +2212,44 @@ send_by_ref: } else { index = offset->value.lval; } + + if (unset_object) { + if (zend_hash_index_find(ht, index, (void **)&object) == FAILURE) { + zend_error(E_ERROR, "Cannot delete non-existing object"); + } + if (Z_TYPE_PP(object) != IS_OBJECT) { + zend_error(E_ERROR, "Cannot call delete on non-object type"); + } + (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle); + } + zend_hash_index_del(ht, index); break; } case IS_STRING: + if (unset_object) { + if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **)&object) == FAILURE) { + zend_error(E_ERROR, "Cannot delete non-existing object"); + } + if (Z_TYPE_PP(object) != IS_OBJECT) { + zend_error(E_ERROR, "Cannot call delete on non-object type"); + } + (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle); + } + zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1); break; case IS_NULL: + if (unset_object) { + if (zend_hash_find(ht, "", sizeof(""), (void **)&object) == FAILURE) { + zend_error(E_ERROR, "Cannot delete non-existing object"); + } + if (Z_TYPE_PP(object) != IS_OBJECT) { + zend_error(E_ERROR, "Cannot call delete on non-object type"); + } + (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle); + } + zend_hash_del(ht, "", sizeof("")); break; default: @@ -2259,7 +2312,6 @@ send_by_ref: PZVAL_LOCK(array); fe_ht = HASH_OF(array); - if (!fe_ht) { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); opline = op_array->opcodes+opline->op2.u.opline_num; @@ -2293,15 +2345,18 @@ send_by_ref: } NEXT_OPCODE(); case ZEND_JMP_NO_CTOR: { - zval *object; + zval *object_zval; + zend_object *object; if (opline->op1.op_type == IS_VAR) { PZVAL_LOCK(*Ts[opline->op1.u.var].var.ptr_ptr); } - object = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); - if (!object->value.obj.ce->handle_function_call - && !zend_hash_exists(&object->value.obj.ce->function_table, object->value.obj.ce->name, object->value.obj.ce->name_length+1)) { + object_zval = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + object = object_zval->value.obj.handlers.get_address(object_zval->value.obj.handle); + + if (!object->ce->handle_function_call + && !zend_hash_exists(&object->ce->function_table, object->ce->name, object->ce->name_length+1)) { opline = op_array->opcodes + opline->op2.u.opline_num; continue; } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1c9e42a5e4..971d00fe0b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -151,7 +151,7 @@ void init_executor(TSRMLS_D) zend_ptr_stack_init(&EG(user_error_handlers)); EG(orig_error_reporting) = EG(error_reporting); - + zend_objects_init(&EG(objects), 1024); #ifdef ZEND_WIN32 EG(timed_out) = 0; #endif @@ -207,6 +207,7 @@ void shutdown_executor(TSRMLS_D) zend_ptr_stack_destroy(&EG(user_error_handlers)); EG(error_reporting) = EG(orig_error_reporting); + zend_objects_destroy(&EG(objects)); } zend_end_try(); } @@ -268,7 +269,7 @@ ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) if ((*zval_ptr)->refcount==0) { zval_dtor(*zval_ptr); safe_free_zval_ptr(*zval_ptr); - } else if (((*zval_ptr)->refcount == 1) && ((*zval_ptr)->type != IS_OBJECT)) { + } else if ((*zval_ptr)->refcount == 1) { (*zval_ptr)->is_ref = 0; } } @@ -411,7 +412,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun } if (object_pp) { if (Z_TYPE_PP(object_pp) == IS_OBJECT) { - function_table = &(*object_pp)->value.obj.ce->function_table; + function_table = &Z_OBJCE_PP(object_pp)->function_table; } else if (Z_TYPE_PP(object_pp) == IS_STRING) { zend_class_entry *ce; char *lc_class; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 65aa6eda74..2e649d0eca 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -200,6 +200,7 @@ struct _zend_executor_globals { int lambda_count; HashTable ini_directives; + zend_objects objects; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 46cce268a8..d5ea4d14f0 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -67,7 +67,7 @@ %left '*' '/' '%' %right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right '[' -%nonassoc T_NEW +%nonassoc T_NEW T_DELETE %token T_EXIT %token T_IF %left T_ELSEIF @@ -201,6 +201,7 @@ unticked_statement: | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 0 TSRMLS_CC); } w_cvar foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } | T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); } | ';' /* empty statement */ + | T_DELETE cvar ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_OBJ TSRMLS_CC); } ; unset_variables: @@ -209,7 +210,7 @@ unset_variables: ; unset_variable: - cvar { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); } + cvar { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_REG TSRMLS_CC); } ; use_filename: diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index f5f79e7ae4..f1bd0393b6 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -765,6 +765,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_NEW; } +"delete" { + return T_DELETE; +} + "var" { return T_VAR; } diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c new file mode 100644 index 0000000000..2380f778fc --- /dev/null +++ b/Zend/zend_objects.c @@ -0,0 +1,122 @@ +#include "zend.h" +#include "zend_globals.h" + +#define ZEND_DEBUG_OBJECTS 0 + +static zend_object_handlers zoh = { + zend_objects_get_address, + NULL, + zend_objects_add_ref, + zend_objects_del_ref, + zend_objects_delete_obj +}; + +void zend_objects_init(zend_objects *objects, zend_uint init_size) +{ + objects->object_buckets = (zend_object_bucket *) emalloc(init_size * sizeof(zend_object_bucket)); + objects->top = 1; /* Skip 0 so that handles are true */ + objects->size = init_size; + objects->free_list_head = -1; +} + +void zend_objects_destroy(zend_objects *objects) +{ + efree(objects->object_buckets); +} + +zend_object_value zend_objects_new(zend_object **object) +{ + TSRMLS_FETCH(); + + zend_object_handle handle; + zend_object_value retval; + + if (EG(objects).free_list_head != -1) { + handle = EG(objects).free_list_head; + EG(objects).free_list_head = EG(objects).object_buckets[handle].bucket.free_list.next; + } else { + if (EG(objects).top == EG(objects).size) { + EG(objects).size <<= 1; + EG(objects).object_buckets = (zend_object_bucket *) erealloc(EG(objects).object_buckets, EG(objects).size * sizeof(zend_object_bucket)); + } + handle = EG(objects).top++; + } + EG(objects).object_buckets[handle].valid = 1; + EG(objects).object_buckets[handle].bucket.obj.refcount = 1; + *object = &EG(objects).object_buckets[handle].bucket.obj.object; + retval.handle = handle; + retval.handlers = zoh; +#if ZEND_DEBUG_OBJECTS + fprintf(stderr, "Allocated object id #%d\n", handle); +#endif + return retval; +} + +zend_object *zend_objects_get_address(zend_object_handle handle) +{ + TSRMLS_FETCH(); + + if (!EG(objects).object_buckets[handle].valid) { + zend_error(E_ERROR, "Trying to access invalid object"); + } + return &EG(objects).object_buckets[handle].bucket.obj.object; +} + +void zend_objects_add_ref(zend_object_handle handle) +{ + TSRMLS_FETCH(); + + if (!EG(objects).object_buckets[handle].valid) { + zend_error(E_ERROR, "Trying to add reference to invalid object"); + } + + EG(objects).object_buckets[handle].bucket.obj.refcount++; +#if ZEND_DEBUG_OBJECTS + fprintf(stderr, "Increased refcount of object id #%d\n", handle); +#endif +} + +void zend_objects_delete_obj(zend_object_handle handle) +{ + zend_object *object; + TSRMLS_FETCH(); + + if (!EG(objects).object_buckets[handle].valid) { + zend_error(E_ERROR, "Trying to delete invalid object"); + } + + object = &EG(objects).object_buckets[handle].bucket.obj.object; + zend_hash_destroy(object->properties); + efree(object->properties); + EG(objects).object_buckets[handle].valid = 0; +#if ZEND_DEBUG_OBJECTS + fprintf(stderr, "Deleted object id #%d\n", handle); +#endif + +} + +void zend_objects_del_ref(zend_object_handle handle) +{ + TSRMLS_FETCH(); + + if (--EG(objects).object_buckets[handle].bucket.obj.refcount == 0) { + zend_object *object; + + if (EG(objects).object_buckets[handle].valid) { + object = &EG(objects).object_buckets[handle].bucket.obj.object; + zend_hash_destroy(object->properties); + efree(object->properties); + } + EG(objects).object_buckets[handle].bucket.free_list.next = EG(objects).free_list_head; + EG(objects).free_list_head = handle; + EG(objects).object_buckets[handle].valid = 0; +#if ZEND_DEBUG_OBJECTS + fprintf(stderr, "Deallocated object id #%d\n", handle); +#endif + } +#if ZEND_DEBUG_OBJECTS + else { + fprintf(stderr, "Decreased refcount of object id #%d\n", handle); + } +#endif +} diff --git a/Zend/zend_objects.h b/Zend/zend_objects.h new file mode 100644 index 0000000000..30660a6666 --- /dev/null +++ b/Zend/zend_objects.h @@ -0,0 +1,34 @@ +#ifndef ZEND_OBJECTS_H +#define ZEND_OBJECTS_H + +#include "zend.h" + +typedef struct _zend_object_bucket { + zend_bool valid; + union _bucket { + struct { + zend_object object; + zend_uint refcount; + } obj; + struct { + int next; + } free_list; + } bucket; +} zend_object_bucket; + +typedef struct _zend_objects { + zend_object_bucket *object_buckets; + zend_uint top; + zend_uint size; + int free_list_head; +} zend_objects; + +void zend_objects_init(zend_objects *objects, zend_uint init_size); +void zend_objects_destroy(zend_objects *objects); +zend_object_value zend_objects_new(zend_object **object); +zend_object *zend_objects_get_address(zend_object_handle handle); +void zend_objects_add_ref(zend_object_handle handle); +void zend_objects_del_ref(zend_object_handle handle); +void zend_objects_delete_obj(zend_object_handle handle); + +#endif /* ZEND_OBJECTS_H */ \ No newline at end of file diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 6df74c790c..b1e2a4410e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -210,16 +210,15 @@ ZEND_API int zend_atoi(const char *str, int str_len); } - #define Z_LVAL(zval) (zval).value.lval #define Z_BVAL(zval) ((zend_bool)(zval).value.lval) #define Z_DVAL(zval) (zval).value.dval #define Z_STRVAL(zval) (zval).value.str.val #define Z_STRLEN(zval) (zval).value.str.len #define Z_ARRVAL(zval) (zval).value.ht -#define Z_OBJ(zval) &(zval).value.obj -#define Z_OBJPROP(zval) (zval).value.obj.properties -#define Z_OBJCE(zval) (zval).value.obj.ce +#define Z_OBJ(zval) (zval).value.obj.handlers.get_address((zval).value.obj.handle) +#define Z_OBJPROP(zval) Z_OBJ(zval)->properties +#define Z_OBJCE(zval) Z_OBJ(zval)->ce #define Z_RESVAL(zval) (zval).value.lval #define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 5cb2ab5d60..757019860c 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -54,8 +54,7 @@ ZEND_API void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC) } break; case IS_OBJECT: - zend_hash_destroy(zvalue->value.obj.properties); - FREE_HASHTABLE(zvalue->value.obj.properties); + zvalue->value.obj.handlers.del_ref(zvalue->value.obj.handle); break; case IS_RESOURCE: { TSRMLS_FETCH(); @@ -119,14 +118,8 @@ ZEND_API int _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC) zend_hash_copy(zvalue->value.ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); } break; - case IS_OBJECT: { - zval *tmp; - HashTable *original_ht = zvalue->value.obj.properties; - - ALLOC_HASHTABLE_REL(zvalue->value.obj.properties); - zend_hash_init(zvalue->value.obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(zvalue->value.obj.properties, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - } + case IS_OBJECT: + zvalue->value.obj.handlers.add_ref(zvalue->value.obj.handle); break; } return SUCCESS;