diff options
Diffstat (limited to 'Zend/zend_types.h')
-rw-r--r-- | Zend/zend_types.h | 74 |
1 files changed, 41 insertions, 33 deletions
diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 82cf20f1b5..dbe2df23de 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -130,7 +130,7 @@ typedef struct { * are only supported since C++20). */ void *ptr; uint32_t type_mask; - /* TODO: We could use the extra 32-bit of padding on 64-bit systems. */ + uint32_t ce_cache__ptr; /* map_ptr offset */ } zend_type; typedef struct { @@ -138,13 +138,15 @@ typedef struct { zend_type types[1]; } zend_type_list; -#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24 -#define _ZEND_TYPE_MASK ((1u << 24) - 1) +#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 25 +#define _ZEND_TYPE_MASK ((1u << 25) - 1) /* Only one of these bits may be set. */ -#define _ZEND_TYPE_NAME_BIT (1u << 23) -#define _ZEND_TYPE_CE_BIT (1u << 22) -#define _ZEND_TYPE_LIST_BIT (1u << 21) +#define _ZEND_TYPE_NAME_BIT (1u << 24) +#define _ZEND_TYPE_CE_BIT (1u << 23) +#define _ZEND_TYPE_LIST_BIT (1u << 22) #define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_CE_BIT|_ZEND_TYPE_NAME_BIT) +/* CE cached in map_ptr area */ +#define _ZEND_TYPE_CACHE_BIT (1u << 21) /* Whether the type list is arena allocated */ #define _ZEND_TYPE_ARENA_BIT (1u << 20) /* Type mask excluding the flags above. */ @@ -167,6 +169,9 @@ typedef struct { #define ZEND_TYPE_HAS_LIST(t) \ ((((t).type_mask) & _ZEND_TYPE_LIST_BIT) != 0) +#define ZEND_TYPE_HAS_CE_CACHE(t) \ + ((((t).type_mask) & _ZEND_TYPE_CACHE_BIT) != 0) + #define ZEND_TYPE_USES_ARENA(t) \ ((((t).type_mask) & _ZEND_TYPE_ARENA_BIT) != 0) @@ -185,6 +190,13 @@ typedef struct { #define ZEND_TYPE_LIST(t) \ ((zend_type_list *) (t).ptr) +#define ZEND_TYPE_CE_CACHE(t) \ + (*(zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR((t).ce_cache)) + +#define ZEND_TYPE_SET_CE_CACHE(t, ce) do { \ + *((zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR((t).ce_cache)) = ce; \ + } while (0) + #define ZEND_TYPE_LIST_SIZE(num_types) \ (sizeof(zend_type_list) + ((num_types) - 1) * sizeof(zend_type)) @@ -254,10 +266,10 @@ typedef struct { (((t).type_mask & _ZEND_TYPE_NULLABLE_BIT) != 0) #define ZEND_TYPE_INIT_NONE(extra_flags) \ - { NULL, (extra_flags) } + { NULL, (extra_flags), 0 } #define ZEND_TYPE_INIT_MASK(_type_mask) \ - { NULL, (_type_mask) } + { NULL, (_type_mask), 0 } #define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \ ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? MAY_BE_BOOL : ((code) == IS_MIXED ? MAY_BE_ANY : (1 << (code)))) \ @@ -265,10 +277,10 @@ typedef struct { #define ZEND_TYPE_INIT_PTR(ptr, type_kind, allow_null, extra_flags) \ { (void *) (ptr), \ - (type_kind) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } + (type_kind) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags), 0 } #define ZEND_TYPE_INIT_PTR_MASK(ptr, type_mask) \ - { (void *) (ptr), (type_mask) } + { (void *) (ptr), (type_mask), 0 } #define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \ ZEND_TYPE_INIT_PTR(_ce, _ZEND_TYPE_CE_BIT, allow_null, extra_flags) @@ -613,6 +625,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc) #define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc) #define GC_TRY_ADDREF(p) zend_gc_try_addref(&(p)->gc) +#define GC_TRY_DELREF(p) zend_gc_try_delref(&(p)->gc) #define GC_TYPE_MASK 0x0000000f #define GC_FLAGS_MASK 0x000003f0 @@ -1130,7 +1143,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #endif #if ZEND_RC_DEBUG -extern ZEND_API zend_bool zend_rc_debug; +extern ZEND_API bool zend_rc_debug; # define ZEND_RC_MOD_CHECK(p) do { \ if (zend_rc_debug && zval_gc_type((p)->u.type_info) != IS_OBJECT) { \ ZEND_ASSERT(!(zval_gc_flags((p)->u.type_info) & GC_IMMUTABLE)); \ @@ -1168,6 +1181,13 @@ static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) { } } +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); @@ -1339,34 +1359,27 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { zend_string *_str = Z_STR_P(_zv); \ ZEND_ASSERT(Z_REFCOUNTED_P(_zv)); \ ZEND_ASSERT(!ZSTR_IS_INTERNED(_str)); \ - Z_DELREF_P(_zv); \ ZVAL_NEW_STR(_zv, zend_string_init( \ ZSTR_VAL(_str), ZSTR_LEN(_str), 0)); \ + GC_DELREF(_str); \ } \ } while (0) #define SEPARATE_ARRAY(zv) do { \ - zval *_zv = (zv); \ - zend_array *_arr = Z_ARR_P(_zv); \ - if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) { \ - if (Z_REFCOUNTED_P(_zv)) { \ - GC_DELREF(_arr); \ - } \ - ZVAL_ARR(_zv, zend_array_dup(_arr)); \ - } \ - } while (0) - -#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \ zval *__zv = (zv); \ - if (Z_TYPE_P(__zv) == IS_ARRAY) { \ - SEPARATE_ARRAY(__zv); \ + zend_array *_arr = Z_ARR_P(__zv); \ + if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) { \ + ZVAL_ARR(__zv, zend_array_dup(_arr)); \ + GC_TRY_DELREF(_arr); \ } \ } while (0) #define SEPARATE_ZVAL_NOREF(zv) do { \ zval *_zv = (zv); \ ZEND_ASSERT(Z_TYPE_P(_zv) != IS_REFERENCE); \ - SEPARATE_ZVAL_IF_NOT_REF(_zv); \ + if (Z_TYPE_P(_zv) == IS_ARRAY) { \ + SEPARATE_ARRAY(_zv); \ + } \ } while (0) #define SEPARATE_ZVAL(zv) do { \ @@ -1384,13 +1397,8 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { break; \ } \ } \ - SEPARATE_ZVAL_IF_NOT_REF(_zv); \ - } while (0) - -#define SEPARATE_ARG_IF_REF(varptr) do { \ - ZVAL_DEREF(varptr); \ - if (Z_REFCOUNTED_P(varptr)) { \ - Z_ADDREF_P(varptr); \ + if (Z_TYPE_P(_zv) == IS_ARRAY) { \ + SEPARATE_ARRAY(_zv); \ } \ } while (0) |