diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-02-12 18:08:11 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-02-12 18:08:11 +0400 |
commit | be82a077769641331ee5914c60df44ba3f862aff (patch) | |
tree | 673803f676ae69c0a3aabc3046feafdf0361b670 | |
parent | 4e66abad54b25ca367fcb6da78524e3c4024e2a0 (diff) | |
download | php-git-be82a077769641331ee5914c60df44ba3f862aff.tar.gz |
Use better data structures (incomplete)
-rw-r--r-- | Zend/zend_API.c | 36 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 9 | ||||
-rw-r--r-- | Zend/zend_hash.c | 9 | ||||
-rw-r--r-- | Zend/zend_iterators.c | 21 | ||||
-rw-r--r-- | Zend/zend_iterators.h | 3 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 33 | ||||
-rw-r--r-- | Zend/zend_objects_API.c | 105 | ||||
-rw-r--r-- | Zend/zend_objects_API.h | 26 | ||||
-rw-r--r-- | Zend/zend_operators.c | 1 | ||||
-rw-r--r-- | Zend/zend_types.h | 24 | ||||
-rw-r--r-- | Zend/zend_variables.c | 14 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 2 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 8 |
13 files changed, 128 insertions, 163 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index cc9275ead4..08d525d15e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1887,7 +1887,7 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TS { int name_len; zend_string *lcname; -//??? zend_module_entry *module_ptr; + zend_module_entry *module_ptr; if (!module) { return NULL; @@ -1923,13 +1923,13 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TS lcname = STR_ALLOC(name_len, 1); zend_str_tolower_copy(lcname->val, module->name, name_len); - if (zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry)) == NULL) { + if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) { zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name); STR_RELEASE(lcname); return NULL; } STR_RELEASE(lcname); -//??? module = module_ptr; + module = module_ptr; EG(current_module) = module; if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { @@ -2798,7 +2798,6 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca EG(scope) = ce_org; } -//??? if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) { if (!zend_is_callable_check_class(Z_STR_P(callable), fcc, &strict_class, error TSRMLS_CC)) { EG(scope) = last_scope; return 0; @@ -3035,11 +3034,12 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) { object_ptr = NULL; } -//??? if (object_ptr && -//??? (!EG(objects_store).object_buckets || -//??? !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) { -//??? return 0; -//??? } + + if (object_ptr && + (!EG(objects_store).object_buckets || + !IS_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)]))) { + return 0; + } switch (Z_TYPE_P(callable)) { case IS_STRING: @@ -3117,10 +3117,10 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch } } else { -//??? if (!EG(objects_store).object_buckets || -//??? !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) { -//??? return 0; -//??? } + if (!!EG(objects_store).object_buckets || + !IS_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(obj)])) { + return 0; + } fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */ @@ -3711,7 +3711,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na ZVAL_COPY_VALUE(property, value); if (Z_REFCOUNT_P(value) > 0) { zval_copy_ctor(property); - } else { +//??? } else { //??? efree(value); } } else { @@ -3849,12 +3849,12 @@ ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) { EG(error_handling) = saved->handling; EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL; - if (Z_TYPE(saved->user_handler) != IS_UNDEF) { -//??? && saved->user_handler != EG(user_error_handler)) { + if (Z_TYPE(saved->user_handler) != IS_UNDEF + && memcmp(&saved->user_handler, &EG(user_error_handler), sizeof(zval)) != 0) { zval_ptr_dtor(&EG(user_error_handler)); ZVAL_COPY_VALUE(&EG(user_error_handler), &saved->user_handler); -//??? } else if (saved->user_handler) { -//??? zval_ptr_dtor(&saved->user_handler); + } else if (Z_TYPE(saved->user_handler)) { + zval_ptr_dtor(&saved->user_handler); } ZVAL_UNDEF(&saved->user_handler); } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index df91e5f0fa..4894250827 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -797,10 +797,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS called_scope = fci_cache->called_scope; fci->object_ptr = fci_cache->object_ptr; ZVAL_COPY_VALUE(&EX(object), fci->object_ptr); -//??? if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT && -//??? (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)].valid)) { -//??? return FAILURE; -//??? } + if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT && + (!EG(objects_store).object_buckets || + !IS_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)]))) { + return FAILURE; + } if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) { if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) { diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 901f6de43a..c3ec0349da 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -510,9 +510,6 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint idx, Buc if (ht->pDestructor) { ht->pDestructor(&p->val); } -//??? if (ht->flags & HASH_FLAG_BIG_DATA) { -//??? pefree(p->xData, ht->flags & HASH_FLAG_PERSISTENT); -//??? } if (p->key) { STR_RELEASE(p->key); } @@ -665,9 +662,6 @@ ZEND_API void zend_hash_destroy(HashTable *ht) if (ht->pDestructor) { ht->pDestructor(&p->val); } -//??? if (ht->flags & HASH_FLAG_BIG_DATA) { -//??? pefree(p->xData, ht->flags & HASH_FLAG_PERSISTENT); -//??? } if (p->key) { STR_RELEASE(p->key); } @@ -696,9 +690,6 @@ ZEND_API void zend_hash_clean(HashTable *ht) if (ht->pDestructor) { ht->pDestructor(&p->val); } -//??? if (ht->flags & HASH_FLAG_BIG_DATA) { -//??? pefree(p->xData, ht->flags & HASH_FLAG_PERSISTENT); -//??? } if (p->key) { STR_RELEASE(p->key); } diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index b433cbe1ab..bb41ab9000 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -24,8 +24,12 @@ static zend_class_entry zend_iterator_class_entry; +static void iter_wrapper_dtor(zend_object *object TSRMLS_DC); + static zend_object_handlers iterator_object_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, + iter_wrapper_dtor, + NULL, + NULL, NULL, /* prop read */ NULL, /* prop write */ NULL, /* read dim */ @@ -61,20 +65,9 @@ static void iter_wrapper_dtor(zend_object *object TSRMLS_DC) iter->funcs->dtor(iter TSRMLS_CC); } -ZEND_API zval *zend_iterator_wrap(zend_object_iterator *iter TSRMLS_DC) +ZEND_API void zend_iterator_wrap(zend_object_iterator *iter, zval *wrapped TSRMLS_DC) { -//??? - return NULL; -#if 0 - zval *wrapped; - - MAKE_STD_ZVAL(wrapped); - Z_TYPE_P(wrapped) = IS_OBJECT; - Z_OBJ_HANDLE_P(wrapped) = zend_objects_store_put(iter, iter_wrapper_dtor, NULL, NULL TSRMLS_CC); - Z_OBJ_HT_P(wrapped) = &iterator_object_handlers; - - return wrapped; -#endif + ZVAL_OBJ(wrapped, &iter->std); } ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap( diff --git a/Zend/zend_iterators.h b/Zend/zend_iterators.h index c0b71e7e37..0ab5bef82a 100644 --- a/Zend/zend_iterators.h +++ b/Zend/zend_iterators.h @@ -55,6 +55,7 @@ typedef struct _zend_object_iterator_funcs { } zend_object_iterator_funcs; struct _zend_object_iterator { + zend_object std; void *data; zend_object_iterator_funcs *funcs; ulong index; /* private to fe_reset/fe_fetch opcodes */ @@ -82,7 +83,7 @@ BEGIN_EXTERN_C() ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(zval *array_ptr, zend_object_iterator **iter TSRMLS_DC); /* given an iterator, wrap it up as a zval for use by the engine opcodes */ -ZEND_API zval *zend_iterator_wrap(zend_object_iterator *iter TSRMLS_DC); +ZEND_API void zend_iterator_wrap(zend_object_iterator *iter, zval *zv TSRMLS_DC); ZEND_API void zend_register_iterator_wrapper(TSRMLS_D); END_EXTERN_C() diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index d05c6b302c..4df8c27fb7 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -41,14 +41,15 @@ #define Z_OBJ_PROTECT_RECURSION(zval_p) \ do { \ - if (EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count++ >= 3) { \ + if (Z_OBJ_APPLY_COUNT_P(zval_p) >= 3) { \ zend_error(E_ERROR, "Nesting level too deep - recursive dependency?"); \ } \ + Z_OBJ_INC_APPLY_COUNT_P(zval_p); \ } while (0) #define Z_OBJ_UNPROTECT_RECURSION(zval_p) \ - EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count-- + Z_OBJ_DEC_APPLY_COUNT_P(zval_p) /* __X accessors explanation: @@ -1010,8 +1011,6 @@ static union _zend_function *zend_std_get_method(zval *object, zend_string *meth if (EXPECTED(key != NULL)) { lc_method_name = Z_STR(key->constant); } else { - /* Create a zend_copy_str_tolower(dest, src, src_length); */ -//??? lc_method_name = do_alloca(method_len+1, use_heap); lc_method_name = STR_ALLOC(method_name->len, 0); zend_str_tolower_copy(lc_method_name->val, method_name->val, method_name->len); } @@ -1146,8 +1145,6 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (EXPECTED(key != NULL)) { lc_function_name = Z_STR(key->constant); } else { - //???lc_function_name = do_alloca(function_name_strlen+1, use_heap); - /* Create a zend_copy_str_tolower(dest, src, src_length); */ lc_function_name = STR_ALLOC(function_name->len, 0); zend_str_tolower_copy(lc_function_name->val, function_name->val, function_name->len); } @@ -1334,38 +1331,38 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ if (!zobj1->properties && !zobj2->properties) { int i; -//??? Z_OBJ_PROTECT_RECURSION(o1); -//??? Z_OBJ_PROTECT_RECURSION(o2); + Z_OBJ_PROTECT_RECURSION(o1); + Z_OBJ_PROTECT_RECURSION(o2); for (i = 0; i < zobj1->ce->default_properties_count; i++) { if (Z_TYPE(zobj1->properties_table[i]) != IS_UNDEF) { if (Z_TYPE(zobj2->properties_table[i]) != IS_UNDEF) { zval result; if (compare_function(&result, &zobj1->properties_table[i], &zobj2->properties_table[i] TSRMLS_CC)==FAILURE) { -//??? Z_OBJ_UNPROTECT_RECURSION(o1); -//??? Z_OBJ_UNPROTECT_RECURSION(o2); + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } if (Z_LVAL(result) != 0) { -//??? Z_OBJ_UNPROTECT_RECURSION(o1); -//??? Z_OBJ_UNPROTECT_RECURSION(o2); + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return Z_LVAL(result); } } else { -//??? Z_OBJ_UNPROTECT_RECURSION(o1); -//??? Z_OBJ_UNPROTECT_RECURSION(o2); + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } } else { if (Z_TYPE(zobj2->properties_table[i]) != IS_UNDEF) { -//??? Z_OBJ_UNPROTECT_RECURSION(o1); -//??? Z_OBJ_UNPROTECT_RECURSION(o2); + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } } } -//??? Z_OBJ_UNPROTECT_RECURSION(o1); -//??? Z_OBJ_UNPROTECT_RECURSION(o2); + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 0; } else { if (!zobj1->properties) { diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 04de616f44..4480512f39 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -23,19 +23,7 @@ #include "zend_globals.h" #include "zend_variables.h" #include "zend_API.h" -#include "zend_objects_API.h" - -#define FREE_BUCKET 1 - -#define IS_VALID(o) (!(((zend_uintptr_t)(o)) & FREE_BUCKET)) - -#define GET_BUCKET_NUMBER(o) (((zend_uintptr_t)(o)) >> 1) - -#define SET_BUCKET_NUMBER(o, n) do { \ - (o) = (((zend_uintptr_t)(n)) << 1) | FREE_BUCKET); \ - } while (0) - - +#include "zend_objects_API.h" ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size) { @@ -99,7 +87,7 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects if (IS_VALID(obj)) { gc_remove_zval_from_buffer((zend_refcounted*)obj TSRMLS_CC); -//??? objects->object_buckets[i].valid = 0; + objects->object_buckets[i] = SET_INVALID(obj); if (obj->handlers->free_obj) { obj->handlers->free_obj(obj TSRMLS_CC); } @@ -129,72 +117,55 @@ ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC) EG(objects_store).object_buckets[handle] = object; } -#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST() \ - EG(objects_store).object_buckets[handle].bucket.free_list.next = EG(objects_store).free_list_head; \ - EG(objects_store).free_list_head = handle; \ - EG(objects_store).object_buckets[handle].valid = 0; +#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle) \ + SET_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \ + EG(objects_store).free_list_head = handle; -/* - * Delete a reference to an objects store entry given the object handle. - */ -//??? -#if 0 -ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */ +ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */ { - struct _store_object *obj; - int failure = 0; - - if (!EG(objects_store).object_buckets) { - return; - } - - obj = &EG(objects_store).object_buckets[handle].bucket.obj; - /* Make sure we hold a reference count during the destructor call otherwise, when the destructor ends the storage might be freed when the refcount reaches 0 a second time */ - if (EG(objects_store).object_buckets[handle].valid) { - if (obj->refcount == 1) { - if (!EG(objects_store).object_buckets[handle].destructor_called) { - EG(objects_store).object_buckets[handle].destructor_called = 1; - - if (obj->dtor) { - if (handlers && !obj->handlers) { - obj->handlers = handlers; - } + if (EG(objects_store).object_buckets && + IS_VALID(EG(objects_store).object_buckets[object->handle])) { + if (object->gc.refcount == 0) { + int failure = 0; + + if (!(object->gc.u.v.flags & IS_OBJ_DESTRUCTOR_CALLED)) { + object->gc.u.v.flags |= IS_OBJ_DESTRUCTOR_CALLED; + + if (object->handlers->dtor_obj) { + object->gc.refcount++; zend_try { - obj->dtor(obj->object, handle TSRMLS_CC); + object->handlers->dtor_obj(object TSRMLS_CC); } zend_catch { failure = 1; } zend_end_try(); + object->gc.refcount--; } } - /* re-read the object from the object store as the store might have been reallocated in the dtor */ - obj = &EG(objects_store).object_buckets[handle].bucket.obj; - - if (obj->refcount == 1) { + if (object->gc.refcount == 0) { //??? GC_REMOVE_ZOBJ_FROM_BUFFER(obj); - if (obj->free_storage) { + if (object->handlers->free_obj) { zend_try { - obj->free_storage(obj->object TSRMLS_CC); + object->handlers->free_obj(object TSRMLS_CC); } zend_catch { failure = 1; } zend_end_try(); } - ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(); + ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(object->handle); } + + if (failure) { + zend_bailout(); + } + } else { + object->gc.refcount--; } } - - obj->refcount--; - - if (failure) { - zend_bailout(); - } } -#endif /* }}} */ //??? @@ -230,28 +201,18 @@ ZEND_API zend_object *zend_objects_store_clone_obj(zval *zobject TSRMLS_DC) * from the constructor function. You MUST NOT use this function for any other * weird games, or call it at any other time after the object is constructed. * */ -//??? -#if 0 -ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC) +ZEND_API void zend_object_store_set_object(zval *zobject, zend_object *object TSRMLS_DC) { - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - - EG(objects_store).object_buckets[handle].bucket.obj.object = object; + EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zobject)] = object; } -#endif /* Called when the ctor was terminated by an exception */ -//??? -#if 0 ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC) { - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle]; - - obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);; - obj_bucket->destructor_called = 1; + zend_object *obj = Z_OBJ_P(zobject); + + obj->gc.u.v.flags |= IS_OBJ_DESTRUCTOR_CALLED; } -#endif /* Proxy objects workings */ typedef struct _zend_proxy_object { diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 9c69e97ed4..3119ee9932 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -51,6 +51,18 @@ //??? } bucket; //???} zend_object_store_bucket; +#define FREE_BUCKET 1 + +#define IS_VALID(o) (!(((zend_uintptr_t)(o)) & FREE_BUCKET)) + +#define SET_INVALID(o) ((zend_object*)((((zend_uintptr_t)(o)) | FREE_BUCKET))) + +#define GET_BUCKET_NUMBER(o) (((zend_uintptr_t)(o)) >> 1) + +#define SET_BUCKET_NUMBER(o, n) do { \ + (o) = (zend_object*)((((zend_uintptr_t)(n)) << 1) | FREE_BUCKET); \ + } while (0) + typedef struct _zend_objects_store { zend_object **object_buckets; zend_uint top; @@ -67,20 +79,10 @@ ZEND_API void zend_objects_store_destroy(zend_objects_store *objects); /* Store API functions */ ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC); +ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC); -//???ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC); -//???ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC); -//???ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC); -//???ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC); -//???static zend_always_inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) { -//??? zend_objects_store_del_ref_by_handle_ex(handle, NULL TSRMLS_CC); -//???} -//???ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC); -//???ZEND_API zend_object *zend_objects_store_clone_obj(zval *object TSRMLS_DC); -//???ZEND_API void *zend_object_store_get_object(const zval *object TSRMLS_DC); -//???ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC); /* See comment in zend_objects_API.c before you use this */ -//???ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC); +ZEND_API void zend_object_store_set_object(zval *zobject, zend_object *object TSRMLS_DC); ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC); ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 2f964d2b89..f0e3a5f98f 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1484,7 +1484,6 @@ static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */ if (Z_REFCOUNT_P(op) == 0) { GC_REMOVE_ZVAL_FROM_BUFFER(op); zval_dtor(op); -//??? FREE_ZVAL(op); } else { zval_ptr_dtor(op); } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index ddf35bcf71..5d143ed11d 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -217,8 +217,28 @@ struct _zend_ast_ref { #define IS_STR_INTERNED (1<<1) /* interned string */ #define IS_STR_PERMANENT (1<<2) /* relives request boundary */ -/* string flags (zval.value->gc.u.vflags) */ -#define IS_OBJ_DESTRUCTOR_CALLED (1<<0) +/* object flags (zval.value->gc.u.vflags) */ +#define IS_OBJ_APPLY_COUNT 0x07 +#define IS_OBJ_DESTRUCTOR_CALLED (1<<3) + +#define Z_OBJ_APPLY_COUNT(zval) \ + (Z_OBJ(zval)->gc.u.v.flags & IS_OBJ_APPLY_COUNT) + +#define Z_OBJ_INC_APPLY_COUNT(zval) do { \ + Z_OBJ(zval)->gc.u.v.flags = \ + (Z_OBJ(zval)->gc.u.v.flags & ~IS_OBJ_APPLY_COUNT) | \ + ((Z_OBJ(zval)->gc.u.v.flags & IS_OBJ_APPLY_COUNT) + 1); \ + } while (0) + +#define Z_OBJ_DEC_APPLY_COUNT(zval) do { \ + Z_OBJ(zval)->gc.u.v.flags = \ + (Z_OBJ(zval)->gc.u.v.flags & ~IS_OBJ_APPLY_COUNT) | \ + ((Z_OBJ(zval)->gc.u.v.flags & IS_OBJ_APPLY_COUNT) - 1); \ + } while (0) + +#define Z_OBJ_APPLY_COUNT_P(zv) Z_OBJ_APPLY_COUNT(*(zv)) +#define Z_OBJ_INC_APPLY_COUNT_P(zv) Z_OBJ_INC_APPLY_COUNT(*(zv)) +#define Z_OBJ_DEC_APPLY_COUNT_P(zv) Z_OBJ_DEC_APPLY_COUNT(*(zv)) #define Z_REFCOUNTED(zval) IS_REFCOUNTED(Z_TYPE(zval)) #define Z_REFCOUNTED_P(zval_p) Z_REFCOUNTED(*(zval_p)) diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index ea31bd5708..799d8e49a3 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -39,23 +39,24 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC) case IS_CONSTANT_ARRAY: { TSRMLS_FETCH(); -//??? if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) { + if (Z_ARRVAL_P(zvalue) != &EG(symbol_table).ht) { /* break possible cycles */ Z_TYPE_P(zvalue) = IS_NULL; zend_hash_destroy(Z_ARRVAL_P(zvalue)); - FREE_HASHTABLE(Z_ARR_P(zvalue)); -//??? } + efree(Z_ARR_P(zvalue)); + } } break; case IS_CONSTANT_AST: zend_ast_destroy(Z_AST_P(zvalue)->ast); + efree(Z_AST_P(zvalue)); break; case IS_OBJECT: { TSRMLS_FETCH(); if (Z_DELREF_P(zvalue) == 0) { - // TODO: release object??? + zend_objects_store_del(Z_OBJ_P(zvalue) TSRMLS_CC); } } break; @@ -216,7 +217,7 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, } } else { if (is_ref) { -//??? SEPARATE_ZVAL_TO_MAKE_IS_REF(p); + SEPARATE_ZVAL_TO_MAKE_IS_REF(p); if (!Z_ISREF_P(p)) { if (IS_REFCOUNTED(Z_TYPE_P(p)) && Z_REFCOUNT_P(p) > 1) { Z_DELREF_P(p); @@ -228,8 +229,7 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, } } } else if (Z_ISREF_P(p)) { -//??? - tmp = *Z_REFVAL_P(p); + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(p)); if (Z_REFCOUNTED(tmp) && Z_REFCOUNT(tmp) > 1) { zval_copy_ctor(&tmp); Z_SET_REFCOUNT(tmp, 0); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7324c1aa64..b52ef6abac 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4158,7 +4158,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) FREE_OP1_IF_VAR(); } if (iter && EXPECTED(EG(exception) == NULL)) { - array_ptr = zend_iterator_wrap(iter TSRMLS_CC); + zend_iterator_wrap(iter, array_ptr TSRMLS_CC); } else { if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) { FREE_OP1_VAR_PTR(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0de8cc1669..ebb0b81092 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3021,7 +3021,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } if (iter && EXPECTED(EG(exception) == NULL)) { - array_ptr = zend_iterator_wrap(iter TSRMLS_CC); + zend_iterator_wrap(iter, array_ptr TSRMLS_CC); } else { if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) { @@ -7995,7 +7995,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (iter && EXPECTED(EG(exception) == NULL)) { - array_ptr = zend_iterator_wrap(iter TSRMLS_CC); + zend_iterator_wrap(iter, array_ptr TSRMLS_CC); } else { if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) { @@ -12989,7 +12989,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval_ptr_dtor_nogc(free_op1.var); } if (iter && EXPECTED(EG(exception) == NULL)) { - array_ptr = zend_iterator_wrap(iter TSRMLS_CC); + zend_iterator_wrap(iter, array_ptr TSRMLS_CC); } else { if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) { if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; @@ -29534,7 +29534,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (iter && EXPECTED(EG(exception) == NULL)) { - array_ptr = zend_iterator_wrap(iter TSRMLS_CC); + zend_iterator_wrap(iter, array_ptr TSRMLS_CC); } else { if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) { |