Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
3 changes: 1 addition & 2 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2937,7 +2937,6 @@ static void zend_convert_internal_arg_info_type(zend_type *type, bool persistent
// temporary workaround, we support union types by splitting
// the type name on `|` characters if necessary.
const char *class_name = ZEND_TYPE_LITERAL_NAME(*type);
type->type_mask &= ~_ZEND_TYPE_LITERAL_NAME_BIT;

size_t num_types = 1;
const char *p = class_name;
Expand All @@ -2951,7 +2950,7 @@ static void zend_convert_internal_arg_info_type(zend_type *type, bool persistent
zend_string *str = zend_string_init_interned(class_name, strlen(class_name), persistent);
zend_alloc_ce_cache(str);
ZEND_TYPE_SET_PTR(*type, str);
type->type_mask |= _ZEND_TYPE_NAME_BIT;
type->kind = _ZEND_TYPE_KIND_NAME;
} else {
/* Union type */
zend_type_list *list = pemalloc(ZEND_TYPE_LIST_SIZE(num_types), persistent);
Expand Down
3 changes: 1 addition & 2 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -7621,8 +7621,7 @@ static zend_type zend_compile_typename_ex(
if (ZEND_TYPE_IS_COMPLEX(single_type)) {
if (!ZEND_TYPE_IS_COMPLEX(type) && !is_composite) {
/* The first class type can be stored directly as the type ptr payload. */
ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
ZEND_TYPE_SET_PTR_AND_KIND(type, ZEND_TYPE_NAME(single_type), _ZEND_TYPE_KIND_NAME);
} else {
if (type_list->num_types == 0) {
/* Switch from single name to name list. */
Expand Down
52 changes: 25 additions & 27 deletions Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,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 kind;
} zend_type;

typedef struct {
Expand All @@ -129,12 +129,6 @@ typedef struct {

#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 << 24)
// Used to signify that type.ptr is not a `zend_string*` but a `const char*`,
#define _ZEND_TYPE_LITERAL_NAME_BIT (1u << 23)
#define _ZEND_TYPE_LIST_BIT (1u << 22)
#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_NAME_BIT|_ZEND_TYPE_LITERAL_NAME_BIT)
/* For BC behaviour with iterable type */
#define _ZEND_TYPE_ITERABLE_BIT (1u << 21)
/* Whether the type list is arena allocated */
Expand All @@ -147,23 +141,28 @@ typedef struct {
#define _ZEND_TYPE_MAY_BE_MASK ((1u << 18) - 1)
/* Must have same value as MAY_BE_NULL */
#define _ZEND_TYPE_NULLABLE_BIT 0x2u
/* zend_type.kind discriminates what type.ptr points at. It is a plain value,
* not a bitmask: exactly one of these applies at a time. */
#define _ZEND_TYPE_KIND_NONE 0u /* no payload; ptr is NULL */
#define _ZEND_TYPE_KIND_NAME 1u /* a `zend_string*` (class name) */
#define _ZEND_TYPE_KIND_LITERAL_NAME 2u /* a `const char*` (literal class name) */
#define _ZEND_TYPE_KIND_LIST 3u /* a `zend_type_list*` */
Comment thread
azjezz marked this conversation as resolved.
Outdated

#define ZEND_TYPE_IS_SET(t) \
(((t).type_mask & _ZEND_TYPE_MASK) != 0)
(((t).type_mask & _ZEND_TYPE_MASK) != 0 || (t).kind != _ZEND_TYPE_KIND_NONE)

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

#define ZEND_TYPE_HAS_NAME(t) \
((((t).type_mask) & _ZEND_TYPE_NAME_BIT) != 0)
((t).kind == _ZEND_TYPE_KIND_NAME)

#define ZEND_TYPE_HAS_LITERAL_NAME(t) \
((((t).type_mask) & _ZEND_TYPE_LITERAL_NAME_BIT) != 0)
((t).kind == _ZEND_TYPE_KIND_LITERAL_NAME)

#define ZEND_TYPE_HAS_LIST(t) \
((((t).type_mask) & _ZEND_TYPE_LIST_BIT) != 0)
((t).kind == _ZEND_TYPE_KIND_LIST)

#define ZEND_TYPE_IS_ITERABLE_FALLBACK(t) \
((((t).type_mask) & _ZEND_TYPE_ITERABLE_BIT) != 0)
Expand Down Expand Up @@ -248,12 +247,11 @@ typedef struct {

#define ZEND_TYPE_SET_PTR_AND_KIND(t, _ptr, kind_bit) do { \
(t).ptr = (_ptr); \
(t).type_mask &= ~_ZEND_TYPE_KIND_MASK; \
(t).type_mask |= (kind_bit); \
(t).kind = (kind_bit); \
} while (0)

#define ZEND_TYPE_SET_LIST(t, list) \
ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_LIST_BIT)
ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_KIND_LIST)

/* FULL_MASK() includes the MAY_BE_* type mask, as well as additional metadata bits.
* The PURE_MASK() only includes the MAY_BE_* type mask. */
Expand Down Expand Up @@ -284,39 +282,39 @@ typedef struct {
#endif

#define ZEND_TYPE_INIT_NONE(extra_flags) \
_ZEND_TYPE_PREFIX { NULL, (extra_flags) }
_ZEND_TYPE_PREFIX { NULL, (extra_flags), 0 }

#define ZEND_TYPE_INIT_MASK(_type_mask) \
_ZEND_TYPE_PREFIX { NULL, (_type_mask) }
_ZEND_TYPE_PREFIX { 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_ITERABLE ? _ZEND_TYPE_ITERABLE_BIT : ((code) == IS_MIXED ? MAY_BE_ANY : (1 << (code))))) \
| ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags))

#define ZEND_TYPE_INIT_PTR(ptr, type_kind, allow_null, extra_flags) \
_ZEND_TYPE_PREFIX { (void *) (ptr), \
(type_kind) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) }
(((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags)), (type_kind) }

#define ZEND_TYPE_INIT_PTR_MASK(ptr, type_mask) \
_ZEND_TYPE_PREFIX { (void *) (ptr), (type_mask) }
_ZEND_TYPE_PREFIX { (void *) (ptr), (type_mask), 0 }

#define ZEND_TYPE_INIT_UNION(ptr, extra_flags) \
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_UNION_BIT) | (extra_flags) }
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_UNION_BIT) | (extra_flags), _ZEND_TYPE_KIND_LIST }

#define ZEND_TYPE_INIT_INTERSECTION(ptr, extra_flags) \
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_INTERSECTION_BIT) | (extra_flags) }
_ZEND_TYPE_PREFIX { (void *) (ptr), (_ZEND_TYPE_INTERSECTION_BIT) | (extra_flags), _ZEND_TYPE_KIND_LIST }

#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags)
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_KIND_NAME, allow_null, extra_flags)

#define ZEND_TYPE_INIT_CLASS_MASK(class_name, type_mask) \
ZEND_TYPE_INIT_PTR_MASK(class_name, _ZEND_TYPE_NAME_BIT | (type_mask))
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_KIND_NAME }

#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_LITERAL_NAME_BIT, allow_null, extra_flags)
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_KIND_LITERAL_NAME, allow_null, extra_flags)

#define ZEND_TYPE_INIT_CLASS_CONST_MASK(class_name, type_mask) \
ZEND_TYPE_INIT_PTR_MASK(class_name, (_ZEND_TYPE_LITERAL_NAME_BIT | (type_mask)))
_ZEND_TYPE_PREFIX { (void *) (class_name), (type_mask), _ZEND_TYPE_KIND_LITERAL_NAME }

typedef union _zend_value {
zend_long lval; /* long value */
Expand Down
16 changes: 10 additions & 6 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -16115,9 +16115,11 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline,
// JIT: if (ZEND_TYPE_IS_SET(property_info->type))
prop_info_ref = ir_LOAD_L(
ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), cache_slot + sizeof(void*) * 2));
if_typed = ir_IF(ir_AND_U32(
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))),
ir_CONST_U32(_ZEND_TYPE_MASK)));
if_typed = ir_IF(ir_OR_U32(
ir_AND_U32(
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))),
ir_CONST_U32(_ZEND_TYPE_MASK)),
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.kind)))));
ir_IF_FALSE(if_typed);
ir_END_list(merge);
ir_IF_TRUE(if_typed);
Expand All @@ -16144,9 +16146,11 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline,
// JIT: if (ZEND_TYPE_IS_SET(property_info->type))
prop_info_ref = ir_LOAD_L(
ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), cache_slot + sizeof(void*) * 2));
if_typed = ir_IF(ir_AND_U32(
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))),
ir_CONST_U32(_ZEND_TYPE_MASK)));
if_typed = ir_IF(ir_OR_U32(
ir_AND_U32(
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.type_mask))),
ir_CONST_U32(_ZEND_TYPE_MASK)),
ir_LOAD_U32(ir_ADD_OFFSET(prop_info_ref, offsetof(zend_property_info, type.kind)))));
ir_IF_FALSE(if_typed);
ir_END_list(merge);
ir_IF_TRUE(if_typed);
Expand Down
Loading