File ds-php81.patch of Package php-pecl-ds

diff --git a/src/common.h b/src/common.h
index cd90519..5ff8cd4 100644
--- a/src/common.h
+++ b/src/common.h
@@ -222,6 +222,17 @@ int name##_unserialize(                 \
     zend_ce_error, \
     "Immutable objects may not be changed")
 
+// https://bugs.php.net/bug.php?id=80816
+#if PHP_VERSION_ID >= 80100
+#define spl_ce_Aggregate     zend_ce_aggregate
+#define spl_ce_ArrayAccess   zend_ce_arrayaccess
+#define spl_ce_Countable     zend_ce_countable
+#define spl_ce_Iterator      zend_ce_iterator
+#define spl_ce_Serializable  zend_ce_serializable
+#define spl_ce_Stringable    zend_ce_stringable
+#define spl_ce_Traversable   zend_ce_traversable
+#endif
+
 /**
  *
  */
diff --git a/src/php/arginfo.h b/src/php/arginfo.h
index 9b2e4b8..605d63e 100644
--- a/src/php/arginfo.h
+++ b/src/php/arginfo.h
@@ -82,6 +82,75 @@ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \
 ZEND_ARG_VARIADIC_INFO(0, v) \
 ZEND_END_ARG_INFO()
 
+#if PHP_VERSION_ID >= 80100
+
+#define ARGINFO_OFFSET_GET(name) \
+    ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_MIXED, 0) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_SET(name) \
+    ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 2, IS_VOID, 0) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+	ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_UNSET(name) \
+    ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_VOID, 0) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#elif PHP_VERSION_ID >= 80000
+
+#define ARGINFO_OFFSET_GET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_SET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 2) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+	ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_UNSET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \
+	ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) \
+    ZEND_END_ARG_INFO()
+
+#else
+
+#define ARGINFO_OFFSET_GET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \
+    ZEND_ARG_INFO(0, offset) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_SET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 2) \
+    ZEND_ARG_INFO(0, offset) \
+    ZEND_ARG_INFO(0, value) \
+    ZEND_END_ARG_INFO()
+
+#define ARGINFO_OFFSET_UNSET(name) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \
+    ZEND_ARG_INFO(0, offset) \
+    ZEND_END_ARG_INFO()
+
+#endif
+
+#if PHP_VERSION_ID >= 80100
+
+#define ARGINFO_NONE_RETURN_TYPE(name, type) \
+    ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, type, 0) \
+    ZEND_END_ARG_INFO()
+#else
+
+#define ARGINFO_NONE_RETURN_TYPE(name, type) \
+    ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \
+    ZEND_END_ARG_INFO()
+
+#endif
+
 #if PHP_VERSION_ID >= 80000
 #define DS_BEGIN_ARG_WITH_RETURN_DS_INFO_EX(name, pass_by_ref, required_num_args, class_name, allow_null) \
     static const zend_internal_arg_info arginfo_##name[] = { \
@@ -110,7 +179,11 @@ ZEND_END_ARG_INFO()
 		{ (const char*)(zend_uintptr_t)(required_num_args), class_name, IS_OBJECT, pass_by_ref, allow_null, 0 },
 #endif
 
-#if PHP_VERSION_ID >= 80000
+#if PHP_VERSION_ID >= 80100
+#define DS_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, pass_by_ref, required_num_args, type, allow_null) \
+    static const zend_internal_arg_info arginfo_##name[] = { \
+        { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)) },
+#elif PHP_VERSION_ID >= 80000
 #define DS_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, pass_by_ref, required_num_args, type, allow_null) \
     static const zend_internal_arg_info arginfo_##name[] = { \
         { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
@@ -178,7 +251,7 @@ ZEND_END_ARG_INFO()
     ZEND_END_ARG_INFO()
 
 #define ARGINFO_NONE_RETURN_OBJ(name, class_name) \
-    DS_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, 0, #class_name, 1) \
+    DS_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, 0, #class_name, 0) \
     ZEND_END_ARG_INFO()
 
 #define ARGINFO_NONE_RETURN_BOOL(name) \
diff --git a/src/php/classes/php_collection_ce.h b/src/php/classes/php_collection_ce.h
index 101ac94..83aec6b 100644
--- a/src/php/classes/php_collection_ce.h
+++ b/src/php/classes/php_collection_ce.h
@@ -21,7 +21,7 @@ ARGINFO_NONE_RETURN_DS(     Collection_copy, Collection);
 ARGINFO_NONE(               Collection_clear);
 ARGINFO_NONE_RETURN_LONG(   Collection_count);
 ARGINFO_NONE_RETURN_BOOL(   Collection_isEmpty);
-ARGINFO_NONE(               Collection_jsonSerialize);
+ARGINFO_NONE_RETURN_TYPE(   Collection_jsonSerialize, IS_MIXED);
 ARGINFO_NONE_RETURN_ARRAY(  Collection_toArray);
 
 void php_ds_register_collection();
diff --git a/src/php/classes/php_map_ce.h b/src/php/classes/php_map_ce.h
index e36f670..c732af2 100644
--- a/src/php/classes/php_map_ce.h
+++ b/src/php/classes/php_map_ce.h
@@ -27,7 +27,7 @@ ARGINFO_NONE_RETURN_DS(                     Map_keys, Set);
 ARGINFO_NONE_RETURN_DS(                     Map_last, Pair);
 ARGINFO_ZVAL_RETURN_DS(                     Map_merge, values, Map);
 ARGINFO_NONE_RETURN_DS(                     Map_pairs, Sequence);
-ARGINFO_NONE(                               Map_jsonSerialize);
+ARGINFO_NONE_RETURN_TYPE(                   Map_jsonSerialize, IS_MIXED);
 ARGINFO_OPTIONAL_CALLABLE_RETURN_DS(        Map_filter, callback, Map);
 ARGINFO_NONE_RETURN_DS(                     Map_first, Pair);
 ARGINFO_CALLABLE_OPTIONAL_ZVAL(             Map_reduce, callback, initial);
@@ -43,9 +43,9 @@ ARGINFO_DS_RETURN_DS(                       Map_xor, map, Map, Map);
 ARGINFO_NONE_RETURN_OBJ(					Map_getIterator, Traversable);
 
 ARGINFO_ZVAL_RETURN_BOOL(                   Map_offsetExists, offset);
-ARGINFO_ZVAL(                               Map_offsetGet, offset);
-ARGINFO_ZVAL_ZVAL(                          Map_offsetSet, offset, value);
-ARGINFO_ZVAL(                               Map_offsetUnset, offset);
+ARGINFO_OFFSET_GET(                         Map_offsetGet);
+ARGINFO_OFFSET_SET(                         Map_offsetSet);
+ARGINFO_OFFSET_UNSET(                       Map_offsetUnset);
 
 void php_ds_register_map();
 
diff --git a/src/php/classes/php_pair_ce.h b/src/php/classes/php_pair_ce.h
index bcbbe74..1ffc95d 100644
--- a/src/php/classes/php_pair_ce.h
+++ b/src/php/classes/php_pair_ce.h
@@ -10,7 +10,7 @@ extern zend_class_entry *php_ds_pair_ce;
 ARGINFO_OPTIONAL_ZVAL_OPTIONAL_ZVAL(    Pair___construct, key, value);
 ARGINFO_NONE_RETURN_DS(                 Pair_copy, Pair);
 ARGINFO_NONE_RETURN_ARRAY(              Pair_toArray);
-ARGINFO_NONE(                           Pair_jsonSerialize);
+ARGINFO_NONE_RETURN_TYPE(               Pair_jsonSerialize, IS_MIXED);
 
 void php_ds_register_pair();
 
diff --git a/src/php/classes/php_queue_ce.c b/src/php/classes/php_queue_ce.c
index cdec675..d7bfd45 100644
--- a/src/php/classes/php_queue_ce.c
+++ b/src/php/classes/php_queue_ce.c
@@ -152,7 +152,11 @@ void php_ds_register_queue()
     php_ds_queue_ce->unserialize    = php_ds_queue_unserialize;
 
     zend_declare_class_constant_long(php_ds_queue_ce, STR_AND_LEN("MIN_CAPACITY"), DS_DEQUE_MIN_CAPACITY);
-    zend_class_implements(php_ds_queue_ce, 1, collection_ce);
+
+    zend_class_implements(php_ds_queue_ce, 2,
+        collection_ce,
+        zend_ce_arrayaccess
+    );
 
     php_ds_register_queue_handlers();
 }
diff --git a/src/php/classes/php_queue_ce.h b/src/php/classes/php_queue_ce.h
index dcd02d4..acdddb8 100644
--- a/src/php/classes/php_queue_ce.h
+++ b/src/php/classes/php_queue_ce.h
@@ -16,9 +16,9 @@ ARGINFO_NONE(                   Queue_peek);
 ARGINFO_NONE_RETURN_OBJ(		Queue_getIterator, Traversable);
 
 ARGINFO_ZVAL_RETURN_BOOL(       Queue_offsetExists, offset);
-ARGINFO_ZVAL(                   Queue_offsetGet, offset);
-ARGINFO_ZVAL_ZVAL(              Queue_offsetSet, offset, value);
-ARGINFO_ZVAL(                   Queue_offsetUnset, offset);
+ARGINFO_OFFSET_GET(             Queue_offsetGet);
+ARGINFO_OFFSET_SET(             Queue_offsetSet);
+ARGINFO_OFFSET_UNSET(           Queue_offsetUnset);
 
 void php_ds_register_queue();
 
diff --git a/src/php/classes/php_sequence_ce.h b/src/php/classes/php_sequence_ce.h
index ec56282..dff20f6 100644
--- a/src/php/classes/php_sequence_ce.h
+++ b/src/php/classes/php_sequence_ce.h
@@ -55,9 +55,9 @@ ARGINFO_NONE(                           Sequence_last);
 ARGINFO_CALLABLE_RETURN_DS(             Sequence_map, callback, Sequence);
 ARGINFO_ZVAL_RETURN_DS(                 Sequence_merge, values, Sequence);
 ARGINFO_ZVAL_RETURN_BOOL(              	Sequence_offsetExists, offset);
-ARGINFO_ZVAL(    						Sequence_offsetGet, offset);
-ARGINFO_ZVAL_ZVAL(                      Sequence_offsetSet, offset, value);
-ARGINFO_ZVAL(                  		    Sequence_offsetUnset, offset);
+ARGINFO_OFFSET_GET(         		    Sequence_offsetGet);
+ARGINFO_OFFSET_SET(                     Sequence_offsetSet);
+ARGINFO_OFFSET_UNSET(          		    Sequence_offsetUnset);
 ARGINFO_NONE(                           Sequence_pop);
 ARGINFO_VARIADIC_ZVAL(                  Sequence_push, values);
 ARGINFO_CALLABLE_OPTIONAL_ZVAL(         Sequence_reduce, callback, initial);
diff --git a/src/php/classes/php_set_ce.c b/src/php/classes/php_set_ce.c
index e3940f2..7087a1f 100644
--- a/src/php/classes/php_set_ce.c
+++ b/src/php/classes/php_set_ce.c
@@ -309,6 +309,10 @@ void php_ds_register_set()
         DS_HTABLE_MIN_CAPACITY
     );
 
-    zend_class_implements(php_ds_set_ce, 1, collection_ce);
+    zend_class_implements(php_ds_set_ce, 2,
+        collection_ce,
+        zend_ce_arrayaccess
+    );
+
     php_ds_register_set_handlers();
 }
diff --git a/src/php/classes/php_set_ce.h b/src/php/classes/php_set_ce.h
index b3c6e65..bdda6d1 100644
--- a/src/php/classes/php_set_ce.h
+++ b/src/php/classes/php_set_ce.h
@@ -34,9 +34,9 @@ ARGINFO_NONE(                               Set_sum);
 ARGINFO_NONE_RETURN_OBJ(                    Set_getIterator, Traversable);
 
 ARGINFO_ZVAL_RETURN_BOOL(                   Set_offsetExists, offset);
-ARGINFO_ZVAL(                               Set_offsetGet, offset);
-ARGINFO_ZVAL_ZVAL(                          Set_offsetSet, offset, value);
-ARGINFO_ZVAL(                               Set_offsetUnset, offset);
+ARGINFO_OFFSET_GET( 	                    Set_offsetGet);
+ARGINFO_OFFSET_SET(                         Set_offsetSet);
+ARGINFO_OFFSET_UNSET(                       Set_offsetUnset);
 
 void php_ds_register_set();
 
diff --git a/src/php/classes/php_stack_ce.h b/src/php/classes/php_stack_ce.h
index 1119b0f..c63a6cd 100644
--- a/src/php/classes/php_stack_ce.h
+++ b/src/php/classes/php_stack_ce.h
@@ -16,9 +16,9 @@ ARGINFO_NONE(                   Stack_peek);
 ARGINFO_NONE_RETURN_OBJ(        Stack_getIterator, Traversable);
 
 ARGINFO_ZVAL_RETURN_BOOL(       Stack_offsetExists, offset);
-ARGINFO_ZVAL(                   Stack_offsetGet, offset);
-ARGINFO_ZVAL_ZVAL(              Stack_offsetSet, offset, value);
-ARGINFO_ZVAL(                   Stack_offsetUnset, offset);
+ARGINFO_OFFSET_GET(             Stack_offsetGet);
+ARGINFO_OFFSET_SET(             Stack_offsetSet);
+ARGINFO_OFFSET_UNSET(           Stack_offsetUnset);
 
 void php_ds_register_stack();
 
diff --git a/src/php/handlers/php_common_handlers.c b/src/php/handlers/php_common_handlers.c
index 7d84dfb..e2441b2 100644
--- a/src/php/handlers/php_common_handlers.c
+++ b/src/php/handlers/php_common_handlers.c
@@ -38,6 +38,7 @@ zval *php_ds_read_dimension_by_key_not_supported
 (zval *obj, zval *offset, int type, zval *rv) {
 #endif
     ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED();
+    return NULL;
 }
 
 int php_ds_has_dimension_by_key_not_supported
@@ -47,6 +48,7 @@ int php_ds_has_dimension_by_key_not_supported
 (zval *obj, zval *offset, int check_empty) {
 #endif
     ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED();
+    return 0;
 }
 
 void php_ds_unset_dimension_by_key_not_supported
@@ -56,4 +58,4 @@ void php_ds_unset_dimension_by_key_not_supported
 (zval *obj, zval *offset) {
 #endif
     ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED();
-}
\ No newline at end of file
+}
diff --git a/src/php/handlers/php_deque_handlers.c b/src/php/handlers/php_deque_handlers.c
index 0bfe187..07ba92c 100644
--- a/src/php/handlers/php_deque_handlers.c
+++ b/src/php/handlers/php_deque_handlers.c
@@ -9,7 +9,7 @@ zend_object_handlers php_deque_handlers;
 static zval *php_ds_deque_read_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int type, zval *return_value) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, zval *offset, int type, zval *return_value) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
@@ -47,7 +47,7 @@ static zval *php_ds_deque_read_dimension
 static void php_ds_deque_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
@@ -69,7 +69,7 @@ static void php_ds_deque_write_dimension
 static int php_ds_deque_has_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int check_empty) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, zval *offset, int check_empty) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
@@ -86,7 +86,7 @@ static int php_ds_deque_has_dimension
 static void php_ds_deque_unset_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, zval *offset) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
@@ -111,24 +111,25 @@ static void php_ds_deque_unset_dimension
 static int php_ds_deque_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    *count = ((php_ds_deque_t*)obj)->deque->size; return SUCCESS;
+    *count = php_ds_deque_fetch_object(obj)->deque->size;
 #else
 (zval *obj, zend_long *count) {
-    *count = Z_DS_DEQUE_P(obj)->size; return SUCCESS;
+    *count = Z_DS_DEQUE_P(obj)->size;
 #endif
+    return SUCCESS;
 }
 
 static void php_ds_deque_free_object(zend_object *object)
 {
-    php_ds_deque_t *obj = (php_ds_deque_t*) object;
-    zend_object_std_dtor(&obj->std);
+    php_ds_deque_t *obj = php_ds_deque_fetch_object(object);
     ds_deque_free(obj->deque);
+    zend_object_std_dtor(&obj->std);
 }
 
 static HashTable *php_ds_deque_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, int *is_temp) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
@@ -142,7 +143,7 @@ static HashTable *php_ds_deque_get_debug_info
 static zend_object *php_ds_deque_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    return php_ds_deque_create_clone(((php_ds_deque_t*)obj)->deque);
+    return php_ds_deque_create_clone(php_ds_deque_fetch_object(obj)->deque);
 #else 
 (zval *obj) {
     return php_ds_deque_create_clone(Z_DS_DEQUE_P(obj));
@@ -152,7 +153,7 @@ static zend_object *php_ds_deque_clone_obj
 static HashTable *php_ds_deque_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_count) {
-    ds_deque_t *deque = ((php_ds_deque_t*)obj)->deque;
+    ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
 #else
 (zval *obj, zval **gc_data, int *gc_count) {
     ds_deque_t *deque = Z_DS_DEQUE_P(obj);
diff --git a/src/php/handlers/php_map_handlers.c b/src/php/handlers/php_map_handlers.c
index 852842e..0b46c5a 100644
--- a/src/php/handlers/php_map_handlers.c
+++ b/src/php/handlers/php_map_handlers.c
@@ -8,7 +8,7 @@ zend_object_handlers php_map_handlers;
 static zval *php_ds_map_read_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int type, zval *rv) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zval *offset, int type, zval *rv) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -46,7 +46,7 @@ static zval *php_ds_map_read_dimension
 static void php_ds_map_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -62,7 +62,7 @@ static void php_ds_map_write_dimension
 static int php_ds_map_has_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int check_empty) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zval *offset, int check_empty) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -74,7 +74,7 @@ static int php_ds_map_has_dimension
 static void php_ds_map_unset_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zval *offset) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -86,7 +86,7 @@ static void php_ds_map_unset_dimension
 static int php_ds_map_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zend_long *count) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -97,15 +97,15 @@ static int php_ds_map_count_elements
 
 static void php_ds_map_free_object(zend_object *object)
 {
-    php_ds_map_t *intern = (php_ds_map_t*) object;
-    zend_object_std_dtor(&intern->std);
+    php_ds_map_t *intern = php_ds_map_fetch_object(object);
     ds_map_free(intern->map);
+    zend_object_std_dtor(&intern->std);
 }
 
 static HashTable *php_ds_map_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, int *is_temp) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -117,7 +117,7 @@ static HashTable *php_ds_map_get_debug_info
 static zend_object *php_ds_map_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -128,7 +128,7 @@ static zend_object *php_ds_map_clone_obj
 static HashTable *php_ds_map_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_size) {
-    ds_map_t *map = ((php_ds_map_t*)obj)->map;
+    ds_map_t *map = php_ds_map_fetch_object(obj)->map;
 #else
 (zval *obj, zval **gc_data, int *gc_size) {
     ds_map_t *map = Z_DS_MAP_P(obj);
@@ -147,7 +147,7 @@ void php_ds_register_map_handlers()
 {
     memcpy(&php_map_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 
-    php_map_handlers.offset             = 0;
+    php_map_handlers.offset             = XtOffsetOf(php_ds_map_t, std);
     php_map_handlers.dtor_obj           = zend_objects_destroy_object;
     php_map_handlers.get_gc             = php_ds_map_get_gc;
     php_map_handlers.free_obj           = php_ds_map_free_object;
diff --git a/src/php/handlers/php_priority_queue_handlers.c b/src/php/handlers/php_priority_queue_handlers.c
index 99cf7e6..cae059e 100644
--- a/src/php/handlers/php_priority_queue_handlers.c
+++ b/src/php/handlers/php_priority_queue_handlers.c
@@ -8,19 +8,19 @@ zend_object_handlers php_priority_queue_handlers;
 
 static void php_ds_priority_queue_free_object(zend_object *object)
 {
-    php_ds_priority_queue_t *queue = (php_ds_priority_queue_t*) object;
-    zend_object_std_dtor(&queue->std);
+    php_ds_priority_queue_t *queue = php_ds_priority_queue_fetch_object(object);
     ds_priority_queue_free(queue->queue);
 
     if (queue->gc_data != NULL) {
         efree(queue->gc_data);
     }
+    zend_object_std_dtor(&queue->std);
 }
 
 static int php_ds_priority_queue_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    ds_priority_queue_t *pq = ((php_ds_priority_queue_t *) obj)->queue;
+    ds_priority_queue_t *pq = php_ds_priority_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, zend_long *count) {
     ds_priority_queue_t *pq = Z_DS_PRIORITY_QUEUE_P(obj);
@@ -32,7 +32,7 @@ static int php_ds_priority_queue_count_elements
 static zend_object *php_ds_priority_queue_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    ds_priority_queue_t *pq = ((php_ds_priority_queue_t *) obj)->queue;
+    ds_priority_queue_t *pq = php_ds_priority_queue_fetch_object(obj)->queue;
 #else
 (zval *obj) {
     ds_priority_queue_t *pq = Z_DS_PRIORITY_QUEUE_P(obj);
@@ -43,7 +43,7 @@ static zend_object *php_ds_priority_queue_clone_obj
 static HashTable *php_ds_priority_queue_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_priority_queue_t *pq = ((php_ds_priority_queue_t *) obj)->queue;
+    ds_priority_queue_t *pq = php_ds_priority_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, int *is_temp) {
     ds_priority_queue_t *pq = Z_DS_PRIORITY_QUEUE_P(obj);
@@ -57,7 +57,7 @@ static HashTable *php_ds_priority_queue_get_debug_info
 static HashTable *php_ds_priority_queue_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_size) {
-    ds_priority_queue_t *pq = ((php_ds_priority_queue_t *) obj)->queue;
+    ds_priority_queue_t *pq = php_ds_priority_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, zval **gc_data, int *gc_size) {
     ds_priority_queue_t *pq = Z_DS_PRIORITY_QUEUE_P(obj);
diff --git a/src/php/handlers/php_queue_handlers.c b/src/php/handlers/php_queue_handlers.c
index 7a00c9e..cd0c78e 100644
--- a/src/php/handlers/php_queue_handlers.c
+++ b/src/php/handlers/php_queue_handlers.c
@@ -10,7 +10,7 @@ zend_object_handlers php_queue_handlers;
 static void php_ds_queue_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_queue_t *queue = ((php_ds_queue_t*)obj)->queue;
+    ds_queue_t *queue = php_ds_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_queue_t *queue = Z_DS_QUEUE_P(obj);
@@ -24,15 +24,15 @@ static void php_ds_queue_write_dimension
 
 static void php_ds_queue_free_object(zend_object *object)
 {
-    php_ds_queue_t *queue = (php_ds_queue_t*) object;
-    zend_object_std_dtor(&queue->std);
+    php_ds_queue_t *queue = php_ds_queue_fetch_object(object);
     ds_queue_free(queue->queue);
+    zend_object_std_dtor(&queue->std);
 }
 
 static int php_ds_queue_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    ds_queue_t *queue = ((php_ds_queue_t*)obj)->queue;
+    ds_queue_t *queue = php_ds_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, zend_long *count) {
     ds_queue_t *queue = Z_DS_QUEUE_P(obj);
@@ -44,7 +44,7 @@ static int php_ds_queue_count_elements
 static zend_object *php_ds_queue_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    ds_queue_t *queue = ((php_ds_queue_t*)obj)->queue;
+    ds_queue_t *queue = php_ds_queue_fetch_object(obj)->queue;
 #else
 (zval *obj) {
     ds_queue_t *queue = Z_DS_QUEUE_P(obj);
@@ -55,7 +55,7 @@ static zend_object *php_ds_queue_clone_obj
 static HashTable *php_ds_queue_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_queue_t *queue = ((php_ds_queue_t*)obj)->queue;
+    ds_queue_t *queue = php_ds_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, int *is_temp) {
     ds_queue_t *queue = Z_DS_QUEUE_P(obj);
@@ -69,7 +69,7 @@ static HashTable *php_ds_queue_get_debug_info
 static HashTable *php_ds_queue_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_count) {
-    ds_queue_t *queue = ((php_ds_queue_t*)obj)->queue;
+    ds_queue_t *queue = php_ds_queue_fetch_object(obj)->queue;
 #else
 (zval *obj, zval **gc_data, int *gc_count) {
     ds_queue_t *queue = Z_DS_QUEUE_P(obj);
diff --git a/src/php/handlers/php_set_handlers.c b/src/php/handlers/php_set_handlers.c
index 93319ec..44dc001 100644
--- a/src/php/handlers/php_set_handlers.c
+++ b/src/php/handlers/php_set_handlers.c
@@ -9,7 +9,7 @@ zend_object_handlers php_ds_set_handlers;
 static zval *php_ds_set_read_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int type, zval *rv) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj, zval *offset, int type, zval *rv) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -30,7 +30,7 @@ static zval *php_ds_set_read_dimension
 static void php_ds_set_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -45,7 +45,7 @@ static void php_ds_set_write_dimension
 static int php_ds_set_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj, zend_long *count) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -56,15 +56,15 @@ static int php_ds_set_count_elements
 
 static void php_ds_set_free_object(zend_object *object)
 {
-    php_ds_set_t *obj = (php_ds_set_t*) object;
-    zend_object_std_dtor(&obj->std);
+    php_ds_set_t *obj = php_ds_set_fetch_object(object);
     ds_set_free(obj->set);
+    zend_object_std_dtor(&obj->std);
 }
 
 static HashTable *php_ds_set_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj, int *is_temp) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -79,7 +79,7 @@ static HashTable *php_ds_set_get_debug_info
 static zend_object *php_ds_set_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -90,7 +90,7 @@ static zend_object *php_ds_set_clone_obj
 static HashTable *php_ds_set_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_count) {
-    ds_set_t *set = ((php_ds_set_t*)obj)->set;
+    ds_set_t *set = php_ds_set_fetch_object(obj)->set;
 #else
 (zval *obj, zval **gc_data, int *gc_count) {
     ds_set_t *set = Z_DS_SET_P(obj);
@@ -110,7 +110,7 @@ void php_ds_register_set_handlers()
 {
     memcpy(&php_ds_set_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 
-    php_ds_set_handlers.offset = 0; // XtOffsetOf(php_ds_set_t, std);
+    php_ds_set_handlers.offset = XtOffsetOf(php_ds_set_t, std);
 
     php_ds_set_handlers.cast_object     = php_ds_default_cast_object;
     php_ds_set_handlers.clone_obj       = php_ds_set_clone_obj;
diff --git a/src/php/handlers/php_stack_handlers.c b/src/php/handlers/php_stack_handlers.c
index 7fe5a7c..a08f15d 100644
--- a/src/php/handlers/php_stack_handlers.c
+++ b/src/php/handlers/php_stack_handlers.c
@@ -8,7 +8,7 @@ zend_object_handlers php_ds_stack_handlers;
 static void php_ds_stack_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_stack_t *stack = ((php_ds_stack_t*)obj)->stack;
+    ds_stack_t *stack = php_ds_stack_fetch_object(obj)->stack;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_stack_t *stack = Z_DS_STACK_P(obj);
@@ -22,15 +22,18 @@ static void php_ds_stack_write_dimension
 
 static void php_ds_stack_free_object(zend_object *object)
 {
-    php_ds_stack_t *obj = (php_ds_stack_t*) object;
+    php_ds_stack_t *obj = php_ds_stack_fetch_object(object);
+	if (obj->stack) {
+	    ds_stack_free(obj->stack);
+		obj->stack = NULL;
+	}
     zend_object_std_dtor(&obj->std);
-    ds_stack_free(obj->stack);
 }
 
 static int php_ds_stack_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    ds_stack_t *stack = ((php_ds_stack_t*)obj)->stack;
+    ds_stack_t *stack = php_ds_stack_fetch_object(obj)->stack;
 #else
 (zval *obj, zend_long *count) {
     ds_stack_t *stack = Z_DS_STACK_P(obj);
@@ -42,7 +45,7 @@ static int php_ds_stack_count_elements
 static zend_object *php_ds_stack_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    ds_stack_t *stack = ((php_ds_stack_t*)obj)->stack;
+    ds_stack_t *stack = php_ds_stack_fetch_object(obj)->stack;
 #else
 (zval *obj) {
     ds_stack_t *stack = Z_DS_STACK_P(obj);
@@ -53,7 +56,7 @@ static zend_object *php_ds_stack_clone_obj
 static HashTable *php_ds_stack_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_stack_t *stack = ((php_ds_stack_t*)obj)->stack;
+    ds_stack_t *stack = php_ds_stack_fetch_object(obj)->stack;
 #else
 (zval *obj, int *is_temp) {
     ds_stack_t *stack = Z_DS_STACK_P(obj);
@@ -68,7 +71,7 @@ static HashTable *php_ds_stack_get_debug_info
 static HashTable *php_ds_stack_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_count) {
-    ds_stack_t *stack = ((php_ds_stack_t*)obj)->stack;
+    ds_stack_t *stack = php_ds_stack_fetch_object(obj)->stack;
 #else
 (zval *obj, zval **gc_data, int *gc_count) {
     ds_stack_t *stack = Z_DS_STACK_P(obj);
diff --git a/src/php/handlers/php_vector_handlers.c b/src/php/handlers/php_vector_handlers.c
index c126be8..58fe1e7 100644
--- a/src/php/handlers/php_vector_handlers.c
+++ b/src/php/handlers/php_vector_handlers.c
@@ -9,7 +9,7 @@ zend_object_handlers php_vector_handlers;
 static zval *php_ds_vector_read_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int type, zval *return_value) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else
 (zval *obj, zval *offset, int type, zval *return_value) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
@@ -47,7 +47,7 @@ static zval *php_ds_vector_read_dimension
 static void php_ds_vector_write_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, zval *value) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else
 (zval *obj, zval *offset, zval *value) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
@@ -69,7 +69,7 @@ static void php_ds_vector_write_dimension
 static int php_ds_vector_has_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset, int check_empty) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else
 (zval *obj, zval *offset, int check_empty) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
@@ -85,7 +85,7 @@ static int php_ds_vector_has_dimension
 static void php_ds_vector_unset_dimension
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval *offset) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else
 (zval *obj, zval *offset) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
@@ -110,7 +110,7 @@ static void php_ds_vector_unset_dimension
 static int php_ds_vector_count_elements
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zend_long *count) {
-    *count = ((php_ds_vector_t*)obj)->vector->size; return SUCCESS;
+    *count = php_ds_vector_fetch_object(obj)->vector->size; return SUCCESS;
 #else 
 (zval *obj, zend_long *count) {
     *count = Z_DS_VECTOR_P(obj)->size; return SUCCESS;
@@ -119,15 +119,15 @@ static int php_ds_vector_count_elements
 
 static void php_ds_vector_free_object(zend_object *obj)
 {
-    php_ds_vector_t *vector = (php_ds_vector_t*) obj;
-    zend_object_std_dtor(&vector->std);
+    php_ds_vector_t *vector = php_ds_vector_fetch_object(obj);
     ds_vector_free(vector->vector);
+    zend_object_std_dtor(&vector->std);
 }
 
 static HashTable *php_ds_vector_get_debug_info
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, int *is_temp) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else
 (zval *obj, int *is_temp) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
@@ -141,7 +141,7 @@ static HashTable *php_ds_vector_get_debug_info
 static zend_object *php_ds_vector_clone_obj
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj) {
-    return php_ds_vector_create_clone(((php_ds_vector_t*)obj)->vector);
+    return php_ds_vector_create_clone(php_ds_vector_fetch_object(obj)->vector);
 #else 
 (zval *obj) {
     return php_ds_vector_create_clone(Z_DS_VECTOR_P(obj));
@@ -151,7 +151,7 @@ static zend_object *php_ds_vector_clone_obj
 static HashTable *php_ds_vector_get_gc
 #if PHP_VERSION_ID >= 80000
 (zend_object *obj, zval **gc_data, int *gc_count) {
-    ds_vector_t *vector = ((php_ds_vector_t*)obj)->vector;
+    ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
 #else 
 (zval *obj, zval **gc_data, int *gc_count) {
     ds_vector_t *vector = Z_DS_VECTOR_P(obj);
diff --git a/src/php/iterators/php_queue_iterator.c b/src/php/iterators/php_queue_iterator.c
index 3a5ebe5..3930b72 100644
--- a/src/php/iterators/php_queue_iterator.c
+++ b/src/php/iterators/php_queue_iterator.c
@@ -4,9 +4,9 @@
 
 static void php_ds_queue_iterator_dtor(zend_object_iterator *iter)
 {
-    zval tmp;
-    ZVAL_OBJ(&tmp, (zend_object *) ((ds_queue_iterator_t *) iter)->queue);
-    zval_ptr_dtor(&tmp);
+    ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter;
+
+    OBJ_RELEASE(iterator->object);
 }
 
 static int php_ds_queue_iterator_valid(zend_object_iterator *iter)
@@ -23,12 +23,12 @@ static void php_ds_queue_iterator_get_current_key(zend_object_iterator *iter, zv
     ZVAL_LONG(key, ((ds_queue_iterator_t *) iter)->position);
 }
 
-static void php_ds_queue_iterator_set_current(php_ds_queue_t *queue, zval *data)
+static void php_ds_queue_iterator_set_current(ds_queue_t *queue, zval *data)
 {
-    if (QUEUE_IS_EMPTY(queue->queue)) {
+    if (QUEUE_IS_EMPTY(queue)) {
         ZVAL_UNDEF(data);
     } else {
-        ds_queue_pop(queue->queue, data);
+        ds_queue_pop(queue, data);
         Z_TRY_DELREF_P(data);
     }
 }
@@ -69,15 +69,16 @@ zend_object_iterator *php_ds_queue_get_iterator(zend_class_entry *ce, zval *obje
     zend_iterator_init((zend_object_iterator*) iterator);
 
     iterator->intern.funcs = &php_ds_queue_iterator_funcs;
-    iterator->queue        = (php_ds_queue_t*) (Z_OBJ_P(object));
+    iterator->queue        = Z_DS_QUEUE_P(object);
+    iterator->object       = Z_OBJ_P(object);
     iterator->position     = 0;
 
     // Add a reference to the object so that it doesn't get collected when
     // the iterated object is implict, eg. foreach ($obj->getInstance() as $value){ ... }
 #if PHP_VERSION_ID >= 70300
-    GC_ADDREF((zend_object *) iterator->queue);
+    GC_ADDREF(iterator->object);
 #else
-    ++GC_REFCOUNT((zend_object *) iterator->queue);
+    ++GC_REFCOUNT(iterator->object);
 #endif
 
     return (zend_object_iterator *) iterator;
diff --git a/src/php/iterators/php_queue_iterator.h b/src/php/iterators/php_queue_iterator.h
index 9221827..ce4295b 100644
--- a/src/php/iterators/php_queue_iterator.h
+++ b/src/php/iterators/php_queue_iterator.h
@@ -7,7 +7,8 @@
 typedef struct _ds_queue_iterator_t {
     zend_object_iterator     intern;
     zend_long                position;
-    php_ds_queue_t          *queue;
+    zend_object             *object;
+    ds_queue_t              *queue;
 } ds_queue_iterator_t;
 
 zend_object_iterator *php_ds_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref);
diff --git a/src/php/iterators/php_stack_iterator.c b/src/php/iterators/php_stack_iterator.c
index f53eb5b..9b62498 100644
--- a/src/php/iterators/php_stack_iterator.c
+++ b/src/php/iterators/php_stack_iterator.c
@@ -4,9 +4,9 @@
 
 static void php_ds_stack_iterator_dtor(zend_object_iterator *iter)
 {
-    zval tmp;
-    ZVAL_OBJ(&tmp, (zend_object *) ((php_ds_stack_iterator_t *) iter)->stack);
-    zval_ptr_dtor(&tmp);
+    php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter;
+
+    OBJ_RELEASE(iterator->object);
 }
 
 static int php_ds_stack_iterator_valid(zend_object_iterator *iter)
@@ -23,12 +23,12 @@ static void php_ds_stack_iterator_get_current_key(zend_object_iterator *iter, zv
     ZVAL_LONG(key, ((php_ds_stack_iterator_t *) iter)->position);
 }
 
-static void php_ds_stack_iterator_set_current(php_ds_stack_t *stack, zval *data)
+static void php_ds_stack_iterator_set_current(ds_stack_t *stack, zval *data)
 {
-    if (DS_STACK_IS_EMPTY(stack->stack)) {
+    if (DS_STACK_IS_EMPTY(stack)) {
         ZVAL_UNDEF(data);
     } else {
-        ds_stack_pop(stack->stack, data);
+        ds_stack_pop(stack, data);
         Z_TRY_DELREF_P(data);
     }
 }
@@ -69,15 +69,16 @@ zend_object_iterator *php_ds_stack_get_iterator(zend_class_entry *ce, zval *obje
     zend_iterator_init((zend_object_iterator*) iterator);
 
     iterator->intern.funcs = &php_ds_stack_iterator_funcs;
-    iterator->stack        = (php_ds_stack_t *) Z_OBJ_P(object);
+    iterator->stack        = Z_DS_STACK_P(object);
+    iterator->object       = Z_OBJ_P(object);
     iterator->position     = 0;
 
     // Add a reference to the object so that it doesn't get collected when
     // the iterated object is implict, eg. foreach ($obj->getInstance() as $value){ ... }
 #if PHP_VERSION_ID >= 70300
-    GC_ADDREF((zend_object *) iterator->stack);
+    GC_ADDREF(iterator->object);
 #else
-    ++GC_REFCOUNT((zend_object *) iterator->stack);
+    ++GC_REFCOUNT(iterator->object);
 #endif
 
     return (zend_object_iterator *) iterator;
diff --git a/src/php/iterators/php_stack_iterator.h b/src/php/iterators/php_stack_iterator.h
index 9ea6857..78563f5 100644
--- a/src/php/iterators/php_stack_iterator.h
+++ b/src/php/iterators/php_stack_iterator.h
@@ -7,7 +7,8 @@
 typedef struct _php_ds_stack_iterator_t {
     zend_object_iterator     intern;
     zend_long                position;
-    php_ds_stack_t          *stack;
+    zend_object             *object;
+    ds_stack_t              *stack;
 } php_ds_stack_iterator_t;
 
 zend_object_iterator *php_ds_stack_get_iterator(zend_class_entry *ce, zval *object, int by_ref);
diff --git a/src/php/objects/php_deque.c b/src/php/objects/php_deque.c
index e8633bf..a27e9b4 100644
--- a/src/php/objects/php_deque.c
+++ b/src/php/objects/php_deque.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_deque_create_object_ex(ds_deque_t *deque)
 {
-    php_ds_deque_t *obj = ecalloc(1, sizeof(php_ds_deque_t));
+#if PHP_VERSION_ID < 70300
+	php_ds_deque_t *obj = ecalloc(1, sizeof(php_ds_deque_t) + zend_object_properties_size(php_ds_deque_ce));
+#else
+    php_ds_deque_t *obj = zend_object_alloc(sizeof(php_ds_deque_t), php_ds_deque_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_deque_ce);
     obj->std.handlers = &php_deque_handlers;
     obj->deque = deque;
diff --git a/src/php/objects/php_deque.h b/src/php/objects/php_deque.h
index 5c95cfe..ddaf354 100644
--- a/src/php/objects/php_deque.h
+++ b/src/php/objects/php_deque.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_deque.h"
 
-#define Z_DS_DEQUE(z)   ((php_ds_deque_t*) Z_OBJ(z))->deque
+typedef struct php_ds_deque {
+    ds_deque_t  *deque;
+    zend_object  std;
+} php_ds_deque_t;
+
+static inline php_ds_deque_t *php_ds_deque_fetch_object(zend_object *obj) {
+	return (php_ds_deque_t *)((char*)(obj) - XtOffsetOf(php_ds_deque_t, std));
+}
+
+#define Z_DS_DEQUE(z)   (php_ds_deque_fetch_object(Z_OBJ(z))->deque)
 #define Z_DS_DEQUE_P(z) Z_DS_DEQUE(*z)
 #define THIS_DS_DEQUE() Z_DS_DEQUE_P(getThis())
 
@@ -21,14 +30,6 @@ do {                                        \
 } while(0)
 
 
-/**
- *
- */
-typedef struct php_ds_deque {
-    zend_object  std;
-    ds_deque_t  *deque;
-} php_ds_deque_t;
-
 /**
  * Creates a new zend_object using an existing deque.
  */
diff --git a/src/php/objects/php_map.c b/src/php/objects/php_map.c
index 820f452..e36e162 100644
--- a/src/php/objects/php_map.c
+++ b/src/php/objects/php_map.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_map_create_object_ex(ds_map_t *map)
 {
-    php_ds_map_t *obj = ecalloc(1, sizeof(php_ds_map_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_map_t *obj = ecalloc(1, sizeof(php_ds_map_t) + zend_object_properties_size(php_ds_map_ce));
+#else
+    php_ds_map_t *obj = zend_object_alloc(sizeof(php_ds_map_t), php_ds_map_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_map_ce);
     obj->std.handlers = &php_map_handlers;
     obj->map = map;
diff --git a/src/php/objects/php_map.h b/src/php/objects/php_map.h
index 8d5ef0a..a3805b4 100644
--- a/src/php/objects/php_map.h
+++ b/src/php/objects/php_map.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_map.h"
 
-#define Z_DS_MAP(z)   (((php_ds_map_t*)(Z_OBJ(z)))->map)
+typedef struct _php_ds_map_t {
+    ds_map_t    *map;
+    zend_object  std;
+} php_ds_map_t;
+
+static inline php_ds_map_t *php_ds_map_fetch_object(zend_object *obj) {
+	return (php_ds_map_t *)((char*)(obj) - XtOffsetOf(php_ds_map_t, std));
+}
+
+#define Z_DS_MAP(z)   (php_ds_map_fetch_object(Z_OBJ(z))->map)
 #define Z_DS_MAP_P(z) Z_DS_MAP(*z)
 #define THIS_DS_MAP() Z_DS_MAP_P(getThis())
 
@@ -20,11 +29,6 @@ do {                                        \
     return;                                 \
 } while(0)
 
-typedef struct _php_ds_map_t {
-    zend_object  std;
-    ds_map_t    *map;
-} php_ds_map_t;
-
 zend_object *php_ds_map_create_object_ex(ds_map_t *map);
 zend_object *php_ds_map_create_object(zend_class_entry *ce);
 zend_object *php_ds_map_create_clone(ds_map_t *map);
diff --git a/src/php/objects/php_pair.c b/src/php/objects/php_pair.c
index 078b9e2..c71a92a 100644
--- a/src/php/objects/php_pair.c
+++ b/src/php/objects/php_pair.c
@@ -4,9 +4,13 @@
 
 zend_object *php_ds_pair_create_object(zend_class_entry *ce)
 {
+#if PHP_VERSION_ID < 70300
     php_ds_pair_t *obj = ecalloc(1, sizeof(php_ds_pair_t) + zend_object_properties_size(ce));
-    zend_object_std_init(&obj->std, php_ds_pair_ce);
-    object_properties_init(&obj->std, php_ds_pair_ce);
+#else
+    php_ds_pair_t *obj = zend_object_alloc(sizeof(php_ds_pair_t), ce);
+#endif
+    zend_object_std_init(&obj->std, ce);
+    object_properties_init(&obj->std, ce);
     obj->std.handlers = &php_pair_handlers;
 
     return &obj->std;
diff --git a/src/php/objects/php_priority_queue.c b/src/php/objects/php_priority_queue.c
index 7fa50c0..7edb9f0 100644
--- a/src/php/objects/php_priority_queue.c
+++ b/src/php/objects/php_priority_queue.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_priority_queue_create_object_ex(ds_priority_queue_t *queue)
 {
-    php_ds_priority_queue_t *obj = ecalloc(1, sizeof(php_ds_priority_queue_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_priority_queue_t *obj = ecalloc(1, sizeof(php_ds_priority_queue_t) + zend_object_properties_size(php_ds_priority_queue_ce));
+#else
+    php_ds_priority_queue_t *obj = zend_object_alloc(sizeof(php_ds_priority_queue_t), php_ds_priority_queue_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_priority_queue_ce);
     obj->std.handlers = &php_priority_queue_handlers;
 
diff --git a/src/php/objects/php_priority_queue.h b/src/php/objects/php_priority_queue.h
index f7a38dc..e26434d 100644
--- a/src/php/objects/php_priority_queue.h
+++ b/src/php/objects/php_priority_queue.h
@@ -3,7 +3,18 @@
 
 #include "../../ds/ds_priority_queue.h"
 
-#define Z_DS_PRIORITY_QUEUE(z)   (((php_ds_priority_queue_t*)(Z_OBJ(z)))->queue)
+typedef struct _php_ds_priority_queue_t {
+    ds_priority_queue_t *queue;
+    zval                *gc_data;
+    int                  gc_size;
+    zend_object          std;
+} php_ds_priority_queue_t;
+
+static inline php_ds_priority_queue_t *php_ds_priority_queue_fetch_object(zend_object *obj) {
+	return (php_ds_priority_queue_t *)((char*)(obj) - XtOffsetOf(php_ds_priority_queue_t, std));
+}
+
+#define Z_DS_PRIORITY_QUEUE(z)   (php_ds_priority_queue_fetch_object(Z_OBJ(z))->queue)
 #define Z_DS_PRIORITY_QUEUE_P(z) Z_DS_PRIORITY_QUEUE(*z)
 #define THIS_DS_PRIORITY_QUEUE() Z_DS_PRIORITY_QUEUE_P(getThis())
 
@@ -21,14 +32,6 @@ do {                                                    \
     return;                                             \
 } while(0)
 
-typedef struct _php_ds_priority_queue_t {
-    zend_object          std;
-    ds_priority_queue_t *queue;
-    zval                *gc_data;
-    int                  gc_size;
-
-} php_ds_priority_queue_t;
-
 zend_object *php_ds_priority_queue_create_object_ex(ds_priority_queue_t *queue);
 zend_object *php_ds_priority_queue_create_object(zend_class_entry *ce);
 zend_object *php_ds_priority_queue_create_clone(ds_priority_queue_t *queue);
diff --git a/src/php/objects/php_queue.c b/src/php/objects/php_queue.c
index 7de656d..fc5d7d9 100644
--- a/src/php/objects/php_queue.c
+++ b/src/php/objects/php_queue.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_queue_create_object_ex(ds_queue_t *queue)
 {
-    php_ds_queue_t *obj = ecalloc(1, sizeof(php_ds_queue_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_queue_t *obj = ecalloc(1, sizeof(php_ds_queue_t) + zend_object_properties_size(php_ds_queue_ce));
+#else
+    php_ds_queue_t *obj = zend_object_alloc(sizeof(php_ds_queue_t), php_ds_queue_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_queue_ce);
     obj->std.handlers = &php_queue_handlers;
     obj->queue = queue;
diff --git a/src/php/objects/php_queue.h b/src/php/objects/php_queue.h
index dc76385..0d2e55c 100644
--- a/src/php/objects/php_queue.h
+++ b/src/php/objects/php_queue.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_queue.h"
 
-#define Z_DS_QUEUE(z)   (((php_ds_queue_t*)(Z_OBJ(z)))->queue)
+typedef struct _php_ds_queue_t {
+    ds_queue_t    *queue;
+    zend_object    std;
+} php_ds_queue_t;
+
+static inline php_ds_queue_t *php_ds_queue_fetch_object(zend_object *obj) {
+	return (php_ds_queue_t *)((char*)(obj) - XtOffsetOf(php_ds_queue_t, std));
+}
+
+#define Z_DS_QUEUE(z)   php_ds_queue_fetch_object(Z_OBJ(z))->queue
 #define Z_DS_QUEUE_P(z) Z_DS_QUEUE(*z)
 #define THIS_DS_QUEUE() Z_DS_QUEUE_P(getThis())
 
@@ -21,11 +30,6 @@ do {                                        \
     return;                                 \
 } while(0)
 
-typedef struct _php_ds_queue_t {
-    zend_object    std;
-    ds_queue_t    *queue;
-} php_ds_queue_t;
-
 zend_object *php_ds_queue_create_object_ex(ds_queue_t *queue);
 zend_object *php_ds_queue_create_object(zend_class_entry *ce);
 zend_object *php_ds_queue_create_clone(ds_queue_t *queue);
diff --git a/src/php/objects/php_set.c b/src/php/objects/php_set.c
index 70d82c0..85027f7 100644
--- a/src/php/objects/php_set.c
+++ b/src/php/objects/php_set.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_set_create_object_ex(ds_set_t *set)
 {
-    php_ds_set_t *obj = ecalloc(1, sizeof(php_ds_set_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_set_t *obj = ecalloc(1, sizeof(php_ds_set_t) + zend_object_properties_size(php_ds_set_ce));
+#else
+    php_ds_set_t *obj = zend_object_alloc(sizeof(php_ds_set_t), php_ds_set_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_set_ce);
     obj->std.handlers = &php_ds_set_handlers;
     obj->set = set;
diff --git a/src/php/objects/php_set.h b/src/php/objects/php_set.h
index 8f94b33..5c2760d 100644
--- a/src/php/objects/php_set.h
+++ b/src/php/objects/php_set.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_set.h"
 
-#define Z_DS_SET(z)   (((php_ds_set_t*)(Z_OBJ(z)))->set)
+typedef struct _php_ds_set_t {
+    ds_set_t      *set;
+    zend_object    std;
+} php_ds_set_t;
+
+static inline php_ds_set_t *php_ds_set_fetch_object(zend_object *obj) {
+	return (php_ds_set_t *)((char*)(obj) - XtOffsetOf(php_ds_set_t, std));
+}
+
+#define Z_DS_SET(z)   (php_ds_set_fetch_object(Z_OBJ(z))->set)
 #define Z_DS_SET_P(z) Z_DS_SET(*z)
 #define THIS_DS_SET() Z_DS_SET_P(getThis())
 
@@ -20,11 +29,6 @@ do {                                        \
     return;                                 \
 } while(0)
 
-typedef struct _php_ds_set_t {
-    zend_object    std;
-    ds_set_t      *set;
-} php_ds_set_t;
-
 zend_object *php_ds_set_create_object_ex(ds_set_t *set);
 zend_object *php_ds_set_create_object(zend_class_entry *ce);
 zend_object *php_ds_set_create_clone(ds_set_t *set);
diff --git a/src/php/objects/php_stack.c b/src/php/objects/php_stack.c
index 8b2ac61..e583ba3 100644
--- a/src/php/objects/php_stack.c
+++ b/src/php/objects/php_stack.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_stack_create_object_ex(ds_stack_t *stack)
 {
-    php_ds_stack_t *obj = ecalloc(1, sizeof(php_ds_stack_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_stack_t *obj = ecalloc(1, sizeof(php_ds_stack_t) + zend_object_properties_size(php_ds_stack_ce));
+#else
+    php_ds_stack_t *obj = zend_object_alloc(sizeof(php_ds_stack_t), php_ds_stack_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_stack_ce);
     obj->std.handlers = &php_ds_stack_handlers;
     obj->stack = stack;
diff --git a/src/php/objects/php_stack.h b/src/php/objects/php_stack.h
index c34934b..219f306 100644
--- a/src/php/objects/php_stack.h
+++ b/src/php/objects/php_stack.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_stack.h"
 
-#define Z_DS_STACK(z)   (((php_ds_stack_t*)(Z_OBJ(z)))->stack)
+typedef struct _php_ds_stack_t {
+    ds_stack_t      *stack;
+    zend_object      std;
+} php_ds_stack_t;
+
+static inline php_ds_stack_t *php_ds_stack_fetch_object(zend_object *obj) {
+	return (php_ds_stack_t *)((char*)(obj) - XtOffsetOf(php_ds_stack_t, std));
+}
+
+#define Z_DS_STACK(z)   php_ds_stack_fetch_object(Z_OBJ(z))->stack
 #define Z_DS_STACK_P(z) Z_DS_STACK(*z)
 #define THIS_DS_STACK() Z_DS_STACK_P(getThis())
 
@@ -20,11 +29,6 @@ do {                                        \
     return;                                 \
 } while(0)
 
-typedef struct _php_ds_stack_t {
-    zend_object      std;
-    ds_stack_t      *stack;
-} php_ds_stack_t;
-
 zend_object *php_ds_stack_create_object_ex(ds_stack_t *stack);
 zend_object *php_ds_stack_create_object(zend_class_entry *ce);
 zend_object *php_ds_stack_create_clone(ds_stack_t *stack);
diff --git a/src/php/objects/php_vector.c b/src/php/objects/php_vector.c
index f415c43..f3402ab 100644
--- a/src/php/objects/php_vector.c
+++ b/src/php/objects/php_vector.c
@@ -6,7 +6,11 @@
 
 zend_object *php_ds_vector_create_object_ex(ds_vector_t *vector)
 {
-    php_ds_vector_t *obj = ecalloc(1, sizeof(php_ds_vector_t));
+#if PHP_VERSION_ID < 70300
+    php_ds_vector_t *obj = ecalloc(1, sizeof(php_ds_vector_t) + zend_object_properties_size(php_ds_vector_ce));
+#else
+    php_ds_vector_t *obj = zend_object_alloc(sizeof(php_ds_vector_t), php_ds_vector_ce);
+#endif
     zend_object_std_init(&obj->std, php_ds_vector_ce);
     obj->std.handlers = &php_vector_handlers;
     obj->vector = vector;
diff --git a/src/php/objects/php_vector.h b/src/php/objects/php_vector.h
index 63b4b7f..43399e6 100644
--- a/src/php/objects/php_vector.h
+++ b/src/php/objects/php_vector.h
@@ -3,7 +3,16 @@
 
 #include "../../ds/ds_vector.h"
 
-#define Z_DS_VECTOR(z)   (((php_ds_vector_t*)(Z_OBJ(z)))->vector)
+typedef struct php_ds_vector {
+    ds_vector_t     *vector;
+    zend_object      std;
+} php_ds_vector_t;
+
+static inline php_ds_vector_t *php_ds_vector_fetch_object(zend_object *obj) {
+	return (php_ds_vector_t *)((char*)(obj) - XtOffsetOf(php_ds_vector_t, std));
+}
+
+#define Z_DS_VECTOR(z)   (php_ds_vector_fetch_object(Z_OBJ(z))->vector)
 #define Z_DS_VECTOR_P(z) Z_DS_VECTOR(*z)
 #define THIS_DS_VECTOR() Z_DS_VECTOR_P(getThis())
 
@@ -20,11 +29,6 @@ do {                                        \
     return;                                 \
 } while(0)
 
-typedef struct php_ds_vector {
-    zend_object      std;
-    ds_vector_t     *vector;
-} php_ds_vector_t;
-
 zend_object *php_ds_vector_create_object_ex(ds_vector_t *vector);
 zend_object *php_ds_vector_create_object(zend_class_entry *ce);
 zend_object *php_ds_vector_create_clone(ds_vector_t *vector);
openSUSE Build Service is sponsored by