Skip to content

Commit 4ebadfb

Browse files
committed
Zend: make zend_type.kind a discriminator enum, not a bit flag
The kind field added in the previous commit was modelled as one-hot bit flags (NAME, LITERAL_NAME, LIST), but exactly one is ever set at a time: it discriminates what type.ptr points at, it is not a bitset like type_mask. Treating it as a bitmask was misleading and forced bit ops where a plain compare suffices. Renumber the values sequentially (NONE=0, NAME=1, LITERAL_NAME=2, LIST=3) and turn the predicates into equality comparisons: IS_COMPLEX kind != NONE HAS_NAME kind == NAME HAS_LITERAL_NAME kind == LITERAL_NAME HAS_LIST kind == LIST Assignment replaces read-modify-write at the few mutation sites (zend_convert_internal_arg_info_type no longer clears then ORs). No behaviour change. Signed-off-by: azjezz <azjezz@protonmail.com>
1 parent 4a761a5 commit 4ebadfb

3 files changed

Lines changed: 21 additions & 23 deletions

File tree

Zend/zend_API.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,7 +2937,6 @@ static void zend_convert_internal_arg_info_type(zend_type *type, bool persistent
29372937
// temporary workaround, we support union types by splitting
29382938
// the type name on `|` characters if necessary.
29392939
const char *class_name = ZEND_TYPE_LITERAL_NAME(*type);
2940-
type->kind &= ~_ZEND_TYPE_LITERAL_NAME_BIT;
29412940

29422941
size_t num_types = 1;
29432942
const char *p = class_name;
@@ -2951,7 +2950,7 @@ static void zend_convert_internal_arg_info_type(zend_type *type, bool persistent
29512950
zend_string *str = zend_string_init_interned(class_name, strlen(class_name), persistent);
29522951
zend_alloc_ce_cache(str);
29532952
ZEND_TYPE_SET_PTR(*type, str);
2954-
type->kind |= _ZEND_TYPE_NAME_BIT;
2953+
type->kind = _ZEND_TYPE_KIND_NAME;
29552954
} else {
29562955
/* Union type */
29572956
zend_type_list *list = pemalloc(ZEND_TYPE_LIST_SIZE(num_types), persistent);

Zend/zend_compile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7621,7 +7621,7 @@ static zend_type zend_compile_typename_ex(
76217621
if (ZEND_TYPE_IS_COMPLEX(single_type)) {
76227622
if (!ZEND_TYPE_IS_COMPLEX(type) && !is_composite) {
76237623
/* The first class type can be stored directly as the type ptr payload. */
7624-
ZEND_TYPE_SET_PTR_AND_KIND(type, ZEND_TYPE_NAME(single_type), _ZEND_TYPE_NAME_BIT);
7624+
ZEND_TYPE_SET_PTR_AND_KIND(type, ZEND_TYPE_NAME(single_type), _ZEND_TYPE_KIND_NAME);
76257625
} else {
76267626
if (type_list->num_types == 0) {
76277627
/* Switch from single name to name list. */

Zend/zend_types.h

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,6 @@ typedef struct {
129129

130130
#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 25
131131
#define _ZEND_TYPE_MASK ((1u << 25) - 1)
132-
/* These bits live in zend_type.kind (not type_mask). Only one may be set.
133-
* Signifies what type.ptr points at: */
134-
#define _ZEND_TYPE_NAME_BIT (1u << 24) /* a `zend_string*` (class name) */
135-
#define _ZEND_TYPE_LITERAL_NAME_BIT (1u << 23) /* a `const char*` (literal class name) */
136-
#define _ZEND_TYPE_LIST_BIT (1u << 22) /* a `zend_type_list*` */
137-
#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_NAME_BIT|_ZEND_TYPE_LITERAL_NAME_BIT)
138132
/* For BC behaviour with iterable type */
139133
#define _ZEND_TYPE_ITERABLE_BIT (1u << 21)
140134
/* Whether the type list is arena allocated */
@@ -147,23 +141,28 @@ typedef struct {
147141
#define _ZEND_TYPE_MAY_BE_MASK ((1u << 18) - 1)
148142
/* Must have same value as MAY_BE_NULL */
149143
#define _ZEND_TYPE_NULLABLE_BIT 0x2u
144+
/* zend_type.kind discriminates what type.ptr points at. It is a plain value,
145+
* not a bitmask: exactly one of these applies at a time. */
146+
#define _ZEND_TYPE_KIND_NONE 0u /* no payload; ptr is NULL */
147+
#define _ZEND_TYPE_KIND_NAME 1u /* a `zend_string*` (class name) */
148+
#define _ZEND_TYPE_KIND_LITERAL_NAME 2u /* a `const char*` (literal class name) */
149+
#define _ZEND_TYPE_KIND_LIST 3u /* a `zend_type_list*` */
150150

151151
#define ZEND_TYPE_IS_SET(t) \
152-
(((t).type_mask & _ZEND_TYPE_MASK) != 0 || (t).kind != 0)
152+
(((t).type_mask & _ZEND_TYPE_MASK) != 0 || (t).kind != _ZEND_TYPE_KIND_NONE)
153153

154-
/* If a type is complex it means it's either a list with a union or intersection,
155-
* or the void pointer is a class name */
154+
/* A complex type carries a ptr payload: a class name or a type list. */
156155
#define ZEND_TYPE_IS_COMPLEX(t) \
157-
((((t).kind) & _ZEND_TYPE_KIND_MASK) != 0)
156+
((t).kind != _ZEND_TYPE_KIND_NONE)
158157

159158
#define ZEND_TYPE_HAS_NAME(t) \
160-
((((t).kind) & _ZEND_TYPE_NAME_BIT) != 0)
159+
((t).kind == _ZEND_TYPE_KIND_NAME)
161160

162161
#define ZEND_TYPE_HAS_LITERAL_NAME(t) \
163-
((((t).kind) & _ZEND_TYPE_LITERAL_NAME_BIT) != 0)
162+
((t).kind == _ZEND_TYPE_KIND_LITERAL_NAME)
164163

165164
#define ZEND_TYPE_HAS_LIST(t) \
166-
((((t).kind) & _ZEND_TYPE_LIST_BIT) != 0)
165+
((t).kind == _ZEND_TYPE_KIND_LIST)
167166

168167
#define ZEND_TYPE_IS_ITERABLE_FALLBACK(t) \
169168
((((t).type_mask) & _ZEND_TYPE_ITERABLE_BIT) != 0)
@@ -252,7 +251,7 @@ typedef struct {
252251
} while (0)
253252

254253
#define ZEND_TYPE_SET_LIST(t, list) \
255-
ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_LIST_BIT)
254+
ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_KIND_LIST)
256255

257256
/* FULL_MASK() includes the MAY_BE_* type mask, as well as additional metadata bits.
258257
* The PURE_MASK() only includes the MAY_BE_* type mask. */
@@ -300,22 +299,22 @@ typedef struct {
300299
_ZEND_TYPE_PREFIX { (void *) (ptr), (type_mask), 0 }
301300

302301
#define ZEND_TYPE_INIT_UNION(ptr, extra_flags) \
303-
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_UNION_BIT) | (extra_flags), _ZEND_TYPE_LIST_BIT }
302+
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_UNION_BIT) | (extra_flags), _ZEND_TYPE_KIND_LIST }
304303

305304
#define ZEND_TYPE_INIT_INTERSECTION(ptr, extra_flags) \
306-
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_INTERSECTION_BIT) | (extra_flags), _ZEND_TYPE_LIST_BIT }
305+
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_INTERSECTION_BIT) | (extra_flags), _ZEND_TYPE_KIND_LIST }
307306

308307
#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \
309-
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags)
308+
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_KIND_NAME, allow_null, extra_flags)
310309

311310
#define ZEND_TYPE_INIT_CLASS_MASK(class_name, type_mask) \
312-
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_NAME_BIT }
311+
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_KIND_NAME }
313312

314313
#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \
315-
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_LITERAL_NAME_BIT, allow_null, extra_flags)
314+
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_KIND_LITERAL_NAME, allow_null, extra_flags)
316315

317316
#define ZEND_TYPE_INIT_CLASS_CONST_MASK(class_name, type_mask) \
318-
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_LITERAL_NAME_BIT }
317+
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_KIND_LITERAL_NAME }
319318

320319
typedef union _zend_value {
321320
zend_long lval; /* long value */

0 commit comments

Comments
 (0)