summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-02-12 18:08:11 +0400
committerDmitry Stogov <dmitry@zend.com>2014-02-12 18:08:11 +0400
commitbe82a077769641331ee5914c60df44ba3f862aff (patch)
tree673803f676ae69c0a3aabc3046feafdf0361b670 /Zend
parent4e66abad54b25ca367fcb6da78524e3c4024e2a0 (diff)
downloadphp-git-be82a077769641331ee5914c60df44ba3f862aff.tar.gz
Use better data structures (incomplete)
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_API.c36
-rw-r--r--Zend/zend_execute_API.c9
-rw-r--r--Zend/zend_hash.c9
-rw-r--r--Zend/zend_iterators.c21
-rw-r--r--Zend/zend_iterators.h3
-rw-r--r--Zend/zend_object_handlers.c33
-rw-r--r--Zend/zend_objects_API.c105
-rw-r--r--Zend/zend_objects_API.h26
-rw-r--r--Zend/zend_operators.c1
-rw-r--r--Zend/zend_types.h24
-rw-r--r--Zend/zend_variables.c14
-rw-r--r--Zend/zend_vm_def.h2
-rw-r--r--Zend/zend_vm_execute.h8
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) {