diff --git a/src/php_tarantool.h b/src/php_tarantool.h index c225b85..635e546 100644 --- a/src/php_tarantool.h +++ b/src/php_tarantool.h @@ -29,6 +29,39 @@ # define smart_string_free_ex(...) smart_str_free_ex(__VA_ARGS__) #endif +#if PHP_VERSION_ID < 70300 +#define GC_ADDREF(p) ++GC_REFCOUNT(p) +#define GC_DELREF(p) --GC_REFCOUNT(p) +#define GC_SET_REFCOUNT(p, rc) GC_REFCOUNT(p) = rc +#endif + + +#if PHP_VERSION_ID < 70300 +# define ARRAY_PROTECT_RECURSION(data) \ + if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) \ + Z_ARRVAL_P(data)->u.v.nApplyCount++; + +# define ARRAY_UNPROTECT_RECURSION(data) \ + if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) \ + Z_ARRVAL_P(data)->u.v.nApplyCount--; + +# define ARRAY_IS_PROTECT_RECURSION(data) \ + (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data)) && Z_ARRVAL_P(data)->u.v.nApplyCount > 1) + +#else +# define ARRAY_PROTECT_RECURSION(data) \ + if (Z_TYPE_P(data) == IS_ARRAY && !(GC_FLAGS(Z_ARRVAL_P(data)) & GC_IMMUTABLE)) \ + GC_PROTECT_RECURSION(Z_ARRVAL_P(data)); + +# define ARRAY_UNPROTECT_RECURSION(data) \ + if (Z_TYPE_P(data) == IS_ARRAY && !(GC_FLAGS(Z_ARRVAL_P(data)) & GC_IMMUTABLE)) \ + GC_UNPROTECT_RECURSION(Z_ARRVAL_P(data)); + +# define ARRAY_IS_PROTECT_RECURSION(data) \ + (Z_TYPE_P(data) == IS_ARRAY && !(GC_FLAGS(Z_ARRVAL_P(data)) & GC_IMMUTABLE) && GC_IS_RECURSIVE(Z_ARRVAL_P(data))) + +#endif + extern zend_module_entry tarantool_module_entry; #define phpext_tarantool_ptr &tarantool_module_entry diff --git a/src/tarantool.c b/src/tarantool.c index 30cccd9..c0a669a 100644 --- a/src/tarantool.c +++ b/src/tarantool.c @@ -1150,7 +1150,7 @@ PHP_METHOD(Tarantool, __construct) { memset(&le, 0, sizeof(zend_resource)); le.type = php_tarantool_list_entry(); le.ptr = obj; - GC_REFCOUNT(&le) = 1; + GC_SET_REFCOUNT(&le, 1); assert(plist_id != NULL); if (zend_hash_update_mem(&EG(persistent_list), plist_id, diff --git a/src/tarantool_msgpack.c b/src/tarantool_msgpack.c index 817e4c5..e0007fe 100644 --- a/src/tarantool_msgpack.c +++ b/src/tarantool_msgpack.c @@ -122,16 +122,12 @@ void php_mp_pack_array_recursively(smart_string *str, zval *val) { size_t key_index = 0; for (; key_index < n; ++key_index) { data = zend_hash_index_find(ht, key_index); - if (!data || data == val || (Z_TYPE_P(data) == IS_ARRAY && - ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data)) && - Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { + if (!data || data == val || ARRAY_IS_PROTECT_RECURSION(data)) { php_mp_pack_nil(str); } else { - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount++; + ARRAY_PROTECT_RECURSION(data); php_mp_pack(str, data); - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount--; + ARRAY_UNPROTECT_RECURSION(data) } } } @@ -165,16 +161,12 @@ void php_mp_pack_hash_recursively(smart_string *str, zval *val) { break; } data = zend_hash_get_current_data_ex(ht, &pos); - if (!data || data == val || (Z_TYPE_P(data) == IS_ARRAY && - ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data)) && - Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { + if (!data || data == val || ARRAY_IS_PROTECT_RECURSION(data)) { php_mp_pack_nil(str); } else { - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount++; + ARRAY_PROTECT_RECURSION(data); php_mp_pack(str, data); - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount--; + ARRAY_UNPROTECT_RECURSION(data); } } } @@ -407,15 +399,12 @@ size_t php_mp_sizeof_array_recursively(zval *val) { for (; key_index < n; ++key_index) { data = zend_hash_index_find(ht, key_index); - if (!data || data == val || - (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data)) && Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { + if (!data || data == val || ARRAY_IS_PROTECT_RECURSION(data)) { needed += php_mp_sizeof_nil(); } else { - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount++; + ARRAY_PROTECT_RECURSION(data); needed += php_mp_sizeof(data); - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount--; + ARRAY_UNPROTECT_RECURSION(data); } } return needed; @@ -451,15 +440,12 @@ size_t php_mp_sizeof_hash_recursively(zval *val) { break; } data = zend_hash_get_current_data_ex(ht, &pos); - if (!data || data == val || - (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data)) && Z_ARRVAL_P(data)->u.v.nApplyCount > 1)) { + if (!data || data == val || ARRAY_IS_PROTECT_RECURSION(data)) { needed += php_mp_sizeof_nil(); } else { - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount++; + ARRAY_PROTECT_RECURSION(data); needed += php_mp_sizeof(data); - if (Z_TYPE_P(data) == IS_ARRAY && ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(data))) - Z_ARRVAL_P(data)->u.v.nApplyCount--; + ARRAY_UNPROTECT_RECURSION(data); } } return needed; diff --git a/src/utils.c b/src/utils.c index 45467af..2c743f4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -29,8 +29,10 @@ const char *tutils_op_to_string(zval *obj) { return "RESOURCE"; case(IS_REFERENCE): return "REFERENCE"; +#if PHP_VERSION_ID < 70300 case(IS_CONSTANT): return "CONSTANT"; +#endif case(IS_CONSTANT_AST): return "CONSTANT_AST"; case(IS_CALLABLE):