Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 110 additions & 110 deletions Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,116 @@ static zend_always_inline uint8_t zval_get_type(const zval* pz) {
#define Z_TYPE_FLAGS_SHIFT 8
#define Z_TYPE_INFO_EXTRA_SHIFT 16

/* zval_gc_flags(zval.value->gc.u.type_info) (common flags) */
#define GC_NOT_COLLECTABLE (1<<4)
#define GC_PROTECTED (1<<5) /* used for recursion detection */
#define GC_IMMUTABLE (1<<6) /* can't be changed in place */
#define GC_PERSISTENT (1<<7) /* allocated using malloc */
#define GC_PERSISTENT_LOCAL (1<<8) /* persistent, but thread-local */

#define GC_TYPE_MASK 0x0000000f
#define GC_FLAGS_MASK 0x000003f0
#define GC_INFO_MASK 0xfffffc00
#define GC_FLAGS_SHIFT 0
#define GC_INFO_SHIFT 10

static zend_always_inline uint8_t zval_gc_type(uint32_t gc_type_info) {
return (gc_type_info & GC_TYPE_MASK);
}

static zend_always_inline uint32_t zval_gc_flags(uint32_t gc_type_info) {
return (gc_type_info >> GC_FLAGS_SHIFT) & (GC_FLAGS_MASK >> GC_FLAGS_SHIFT);
}

static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
return (gc_type_info >> GC_INFO_SHIFT);
}

#define GC_TYPE_INFO(p) (p)->gc.u.type_info
#define GC_TYPE(p) zval_gc_type(GC_TYPE_INFO(p))
#define GC_FLAGS(p) zval_gc_flags(GC_TYPE_INFO(p))
#define GC_INFO(p) zval_gc_info(GC_TYPE_INFO(p))

#define GC_ADD_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) |= (flags) << GC_FLAGS_SHIFT; \
} while (0)
#define GC_DEL_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) &= ~((flags) << GC_FLAGS_SHIFT); \
} while (0)

#ifndef ZEND_RC_DEBUG
# define ZEND_RC_DEBUG 0
#endif

#if ZEND_RC_DEBUG
extern ZEND_API bool zend_rc_debug;
/* The GC_PERSISTENT flag is reused for IS_OBJ_WEAKLY_REFERENCED on objects.
* Skip checks for OBJECT/NULL type to avoid interpreting the flag incorrectly. */
# define ZEND_RC_MOD_CHECK(p) do { \
if (zend_rc_debug) { \
uint8_t type = zval_gc_type((p)->u.type_info); \
if (type != IS_OBJECT && type != IS_NULL) { \
ZEND_ASSERT(!(zval_gc_flags((p)->u.type_info) & GC_IMMUTABLE)); \
ZEND_ASSERT((zval_gc_flags((p)->u.type_info) & (GC_PERSISTENT|GC_PERSISTENT_LOCAL)) != GC_PERSISTENT); \
} \
} \
} while (0)
# define GC_MAKE_PERSISTENT_LOCAL(p) do { \
GC_ADD_FLAGS(p, GC_PERSISTENT_LOCAL); \
} while (0)
#else
# define ZEND_RC_MOD_CHECK(p) \
do { } while (0)
# define GC_MAKE_PERSISTENT_LOCAL(p) \
do { } while (0)
#endif

static zend_always_inline uint32_t zend_gc_refcount(const zend_refcounted_h *p) {
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_set_refcount(zend_refcounted_h *p, uint32_t rc) {
p->refcount = rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return ++(p->refcount);
}

static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
++p->refcount;
}
}

static zend_always_inline void zend_gc_try_delref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
--p->refcount;
}
}

static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
ZEND_ASSERT(p->refcount > 0);
ZEND_RC_MOD_CHECK(p);
return --(p->refcount);
}

static zend_always_inline uint32_t zend_gc_addref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount += rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount -= rc;
return p->refcount;
}

#define GC_REFCOUNT(p) zend_gc_refcount(&(p)->gc)
#define GC_SET_REFCOUNT(p, rc) zend_gc_set_refcount(&(p)->gc, rc)
#define GC_ADDREF(p) zend_gc_addref(&(p)->gc)
Expand Down Expand Up @@ -754,36 +864,6 @@ static zend_always_inline uint8_t zval_get_type(const zval* pz) {
} \
} while (0)

#define GC_TYPE_MASK 0x0000000f
#define GC_FLAGS_MASK 0x000003f0
#define GC_INFO_MASK 0xfffffc00
#define GC_FLAGS_SHIFT 0
#define GC_INFO_SHIFT 10

static zend_always_inline uint8_t zval_gc_type(uint32_t gc_type_info) {
return (gc_type_info & GC_TYPE_MASK);
}

static zend_always_inline uint32_t zval_gc_flags(uint32_t gc_type_info) {
return (gc_type_info >> GC_FLAGS_SHIFT) & (GC_FLAGS_MASK >> GC_FLAGS_SHIFT);
}

static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
return (gc_type_info >> GC_INFO_SHIFT);
}

#define GC_TYPE_INFO(p) (p)->gc.u.type_info
#define GC_TYPE(p) zval_gc_type(GC_TYPE_INFO(p))
#define GC_FLAGS(p) zval_gc_flags(GC_TYPE_INFO(p))
#define GC_INFO(p) zval_gc_info(GC_TYPE_INFO(p))

#define GC_ADD_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) |= (flags) << GC_FLAGS_SHIFT; \
} while (0)
#define GC_DEL_FLAGS(p, flags) do { \
GC_TYPE_INFO(p) &= ~((flags) << GC_FLAGS_SHIFT); \
} while (0)

#define Z_GC_TYPE(zval) GC_TYPE(Z_COUNTED(zval))
#define Z_GC_TYPE_P(zval_p) Z_GC_TYPE(*(zval_p))

Expand All @@ -795,13 +875,6 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
#define Z_GC_TYPE_INFO(zval) GC_TYPE_INFO(Z_COUNTED(zval))
#define Z_GC_TYPE_INFO_P(zval_p) Z_GC_TYPE_INFO(*(zval_p))

/* zval_gc_flags(zval.value->gc.u.type_info) (common flags) */
#define GC_NOT_COLLECTABLE (1<<4)
#define GC_PROTECTED (1<<5) /* used for recursion detection */
#define GC_IMMUTABLE (1<<6) /* can't be changed in place */
#define GC_PERSISTENT (1<<7) /* allocated using malloc */
#define GC_PERSISTENT_LOCAL (1<<8) /* persistent, but thread-local */

#define GC_NULL (IS_NULL | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_STRING (IS_STRING | (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT))
#define GC_ARRAY IS_ARRAY
Expand Down Expand Up @@ -1299,79 +1372,6 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z))
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))

#ifndef ZEND_RC_DEBUG
# define ZEND_RC_DEBUG 0
#endif

#if ZEND_RC_DEBUG
extern ZEND_API bool zend_rc_debug;
/* The GC_PERSISTENT flag is reused for IS_OBJ_WEAKLY_REFERENCED on objects.
* Skip checks for OBJECT/NULL type to avoid interpreting the flag incorrectly. */
# define ZEND_RC_MOD_CHECK(p) do { \
if (zend_rc_debug) { \
uint8_t type = zval_gc_type((p)->u.type_info); \
if (type != IS_OBJECT && type != IS_NULL) { \
ZEND_ASSERT(!(zval_gc_flags((p)->u.type_info) & GC_IMMUTABLE)); \
ZEND_ASSERT((zval_gc_flags((p)->u.type_info) & (GC_PERSISTENT|GC_PERSISTENT_LOCAL)) != GC_PERSISTENT); \
} \
} \
} while (0)
# define GC_MAKE_PERSISTENT_LOCAL(p) do { \
GC_ADD_FLAGS(p, GC_PERSISTENT_LOCAL); \
} while (0)
#else
# define ZEND_RC_MOD_CHECK(p) \
do { } while (0)
# define GC_MAKE_PERSISTENT_LOCAL(p) \
do { } while (0)
#endif

static zend_always_inline uint32_t zend_gc_refcount(const zend_refcounted_h *p) {
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_set_refcount(zend_refcounted_h *p, uint32_t rc) {
p->refcount = rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return ++(p->refcount);
}

static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
++p->refcount;
}
}

static zend_always_inline void zend_gc_try_delref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
--p->refcount;
}
}

static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
ZEND_ASSERT(p->refcount > 0);
ZEND_RC_MOD_CHECK(p);
return --(p->refcount);
}

static zend_always_inline uint32_t zend_gc_addref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount += rc;
return p->refcount;
}

static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount -= rc;
return p->refcount;
}

static zend_always_inline uint32_t zval_refcount_p(const zval* pz) {
#if ZEND_DEBUG
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_TYPE_P(pz) == IS_ARRAY);
Expand Down
Loading