Skip to content

Commit ac4e0f0

Browse files
committed
Make zend_type a 2-field struct
We now store the pointer payload and the type mask separately. This is in preparation for union types, where we will be using both at the same time. To avoid increasing the size of arginfo structures, the pass_by_reference and is_variadic fields are now stored as part of the type_mask (8-bit are reserved for custom use). Different types of pointer payloads are distinguished based on bits in the type_mask.
1 parent a555cc0 commit ac4e0f0

28 files changed

+265
-268
lines changed

Zend/zend.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,7 @@ static void function_copy_ctor(zval *zv) /* {{{ */
594594
for (i = 0 ; i < num_args; i++) {
595595
if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
596596
zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1);
597-
598-
new_arg_info[i].type =
599-
ZEND_TYPE_ENCODE_CLASS(
600-
name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type));
597+
ZEND_TYPE_SET_PTR(new_arg_info[i].type, name);
601598
}
602599
}
603600
func->common.arg_info = new_arg_info + 1;
@@ -968,7 +965,7 @@ static void zend_resolve_property_types(void) /* {{{ */
968965
zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name);
969966

970967
ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS);
971-
prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
968+
prop_info->type = (zend_type) ZEND_TYPE_INIT_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type), 0);
972969
zend_string_release(lc_type_name);
973970
zend_string_release(type_name);
974971
}

Zend/zend_API.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,21 +2045,17 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
20452045
} else {
20462046
internal_function->required_num_args = info->required_num_args;
20472047
}
2048-
if (info->return_reference) {
2048+
if (ZEND_ARG_SEND_MODE(info)) {
20492049
internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
20502050
}
2051-
if (ptr->arg_info[ptr->num_args].is_variadic) {
2051+
if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
20522052
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
20532053
/* Don't count the variadic argument */
20542054
internal_function->num_args--;
20552055
}
20562056
if (ZEND_TYPE_IS_SET(info->type)) {
20572057
if (ZEND_TYPE_IS_CLASS(info->type)) {
2058-
const char *type_name = (const char*)info->type;
2059-
2060-
if (type_name[0] == '?') {
2061-
type_name++;
2062-
}
2058+
const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
20632059
if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
20642060
zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
20652061
}
@@ -2140,16 +2136,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
21402136
reg_function->common.arg_info = new_arg_info + 1;
21412137
for (i = 0; i < num_args; i++) {
21422138
if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) {
2143-
const char *class_name = (const char*)new_arg_info[i].type;
2144-
zend_bool allow_null = 0;
2145-
zend_string *str;
2146-
2147-
if (class_name[0] == '?') {
2148-
class_name++;
2149-
allow_null = 1;
2150-
}
2151-
str = zend_string_init_interned(class_name, strlen(class_name), 1);
2152-
new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
2139+
const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
2140+
ZEND_TYPE_SET_PTR(new_arg_info[i].type,
2141+
zend_string_init_interned(class_name, strlen(class_name), 1));
21532142
}
21542143
}
21552144
}
@@ -3715,7 +3704,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze
37153704

37163705
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
37173706
{
3718-
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, ZEND_TYPE_ENCODE_NONE());
3707+
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
37193708
}
37203709
/* }}} */
37213710

Zend/zend_API.h

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,34 +96,45 @@ typedef struct _zend_fcall_info_cache {
9696

9797
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
9898

99-
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 0},
100-
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, pass_by_ref, 0},
101-
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 },
102-
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
103-
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
104-
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 0 },
105-
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 1 },
106-
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 1 },
107-
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 },
99+
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \
100+
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0))
101+
102+
#define ZEND_ARG_INFO(pass_by_ref, name) \
103+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0))},
104+
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
105+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
106+
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \
107+
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
108+
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \
109+
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
110+
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
111+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
112+
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
113+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) },
114+
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
115+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) },
116+
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
117+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) },
108118

109119
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
110120
static const zend_internal_arg_info name[] = { \
111-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CLASS_CONST(#class_name, allow_null), return_reference, 0 },
121+
{ (const char*)(zend_uintptr_t)(required_num_args), \
122+
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) },
112123

113124
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
114125
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
115126

116127
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
117128
static const zend_internal_arg_info name[] = { \
118-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CODE(type, allow_null), return_reference, 0 },
129+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) },
119130
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
120131
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
121132

122133
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
123134
static const zend_internal_arg_info name[] = { \
124-
{ (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 },
135+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)) },
125136
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
126-
ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1)
137+
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
127138
#define ZEND_END_ARG_INFO() };
128139

129140
/* Name macros */

Zend/zend_closures.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -557,16 +557,16 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp)
557557
if (arg_info->name) {
558558
if (zstr_args) {
559559
name = zend_strpprintf(0, "%s$%s",
560-
arg_info->pass_by_reference ? "&" : "",
560+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
561561
ZSTR_VAL(arg_info->name));
562562
} else {
563563
name = zend_strpprintf(0, "%s$%s",
564-
arg_info->pass_by_reference ? "&" : "",
564+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
565565
((zend_internal_arg_info*)arg_info)->name);
566566
}
567567
} else {
568568
name = zend_strpprintf(0, "%s$param%d",
569-
arg_info->pass_by_reference ? "&" : "",
569+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
570570
i + 1);
571571
}
572572
ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));

Zend/zend_compile.c

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
11351135
} else if (ZEND_TYPE_IS_CE(type)) {
11361136
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
11371137
} else {
1138-
uint32_t type_mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type));
1138+
uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type);
11391139
switch (type_mask) {
11401140
case MAY_BE_FALSE|MAY_BE_TRUE:
11411141
str = ZSTR_KNOWN(ZEND_STR_BOOL);
@@ -1199,7 +1199,7 @@ static void zend_mark_function_as_generator() /* {{{ */
11991199
|| zend_string_equals_literal_ci(name, "Iterator")
12001200
|| zend_string_equals_literal_ci(name, "Generator");
12011201
} else {
1202-
valid_type = (ZEND_TYPE_MASK(return_info.type) & MAY_BE_ITERABLE) != 0;
1202+
valid_type = (ZEND_TYPE_FULL_MASK(return_info.type) & MAY_BE_ITERABLE) != 0;
12031203
}
12041204

12051205
if (!valid_type) {
@@ -2175,7 +2175,7 @@ static void zend_emit_return_type_check(
21752175
zend_op *opline;
21762176

21772177
/* `return ...;` is illegal in a void function (but `return;` isn't) */
2178-
if (ZEND_TYPE_IS_MASK(type) && ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
2178+
if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
21792179
if (expr) {
21802180
if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
21812181
zend_error_noreturn(E_COMPILE_ERROR,
@@ -2201,8 +2201,7 @@ static void zend_emit_return_type_check(
22012201
}
22022202

22032203
if (expr && expr->op_type == IS_CONST) {
2204-
if (ZEND_TYPE_IS_MASK(type)
2205-
&& ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
2204+
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
22062205
/* we don't need run-time check */
22072206
return;
22082207
}
@@ -5359,11 +5358,11 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
53595358
n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
53605359
i = 0;
53615360
while (i < n) {
5362-
ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference);
5361+
ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i]));
53635362
i++;
53645363
}
5365-
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) {
5366-
uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference;
5364+
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) {
5365+
uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]);
53675366
while (i < MAX_ARG_FLAG_NUM) {
53685367
ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
53695368
i++;
@@ -5382,7 +5381,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53825381
}
53835382

53845383
if (ast->kind == ZEND_AST_TYPE) {
5385-
return ZEND_TYPE_ENCODE_CODE(ast->attr, allow_null);
5384+
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null, 0);
53865385
} else {
53875386
zend_string *class_name = zend_ast_get_str(ast);
53885387
zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
@@ -5396,7 +5395,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53965395
if (type == IS_VOID && allow_null) {
53975396
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
53985397
}
5399-
return ZEND_TYPE_ENCODE_CODE(type, allow_null);
5398+
return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null, 0);
54005399
} else {
54015400
const char *correct_name;
54025401
zend_string *orig_name = zend_ast_get_str(ast);
@@ -5428,7 +5427,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
54285427
}
54295428
}
54305429

5431-
return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null);
5430+
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null, 0);
54325431
}
54335432
}
54345433
}
@@ -5448,12 +5447,12 @@ static zend_bool zend_is_valid_default_value(zend_type type, zval *value)
54485447
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
54495448
return 1;
54505449
}
5451-
if ((ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
5450+
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
54525451
/* Integers are allowed as initializers for floating-point values. */
54535452
convert_to_double(value);
54545453
return 1;
54555454
}
5456-
if ((ZEND_TYPE_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
5455+
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
54575456
return 1;
54585457
}
54595458
return 0;
@@ -5470,9 +5469,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
54705469
/* Use op_array->arg_info[-1] for return type */
54715470
arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
54725471
arg_infos->name = NULL;
5473-
arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
5474-
arg_infos->is_variadic = 0;
54755472
arg_infos->type = zend_compile_typename(return_type_ast, 0);
5473+
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
5474+
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
54765475
arg_infos++;
54775476
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
54785477
} else {
@@ -5540,23 +5539,18 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
55405539

55415540
arg_info = &arg_infos[i];
55425541
arg_info->name = zend_string_copy(name);
5543-
arg_info->pass_by_reference = is_ref;
5544-
arg_info->is_variadic = is_variadic;
5545-
arg_info->type = ZEND_TYPE_ENCODE_NONE();
5542+
arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0);
55465543

55475544
if (type_ast) {
55485545
uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
55495546

5550-
uint32_t arg_type;
55515547
zend_bool is_class;
55525548

55535549
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
55545550
arg_info->type = zend_compile_typename(type_ast, default_type == IS_NULL);
5555-
55565551
is_class = ZEND_TYPE_IS_CLASS(arg_info->type);
5557-
arg_type = !is_class ? ZEND_TYPE_MASK(arg_info->type) : 0;
55585552

5559-
if (arg_type & MAY_BE_VOID) {
5553+
if (!is_class && (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID)) {
55605554
zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
55615555
}
55625556

@@ -5580,6 +5574,8 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
55805574
opline->extended_value = zend_alloc_cache_slot();
55815575
}
55825576
}
5577+
5578+
ZEND_TYPE_FULL_MASK(arg_info->type) |= _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic);
55835579
}
55845580

55855581
/* These are assigned at the end to avoid uninitialized memory in case of an error */
@@ -6079,13 +6075,12 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /
60796075
zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
60806076
zend_string *doc_comment = NULL;
60816077
zval value_zv;
6082-
zend_type type = ZEND_TYPE_ENCODE_NONE();
6078+
zend_type type = ZEND_TYPE_INIT_NONE(0);
60836079

60846080
if (type_ast) {
60856081
type = zend_compile_typename(type_ast, 0);
60866082

6087-
if (ZEND_TYPE_IS_MASK(type)
6088-
&& (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE))) {
6083+
if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
60896084
zend_string *str = zend_type_to_string(type);
60906085
zend_error_noreturn(E_COMPILE_ERROR,
60916086
"Property %s::$%s cannot have type %s",

Zend/zend_compile.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -383,16 +383,12 @@ typedef struct _zend_class_constant {
383383
typedef struct _zend_internal_arg_info {
384384
const char *name;
385385
zend_type type;
386-
zend_uchar pass_by_reference;
387-
zend_bool is_variadic;
388386
} zend_internal_arg_info;
389387

390388
/* arg_info for user functions */
391389
typedef struct _zend_arg_info {
392390
zend_string *name;
393391
zend_type type;
394-
zend_uchar pass_by_reference;
395-
zend_bool is_variadic;
396392
} zend_arg_info;
397393

398394
/* the following structure repeats the layout of zend_internal_arg_info,
@@ -403,8 +399,6 @@ typedef struct _zend_arg_info {
403399
typedef struct _zend_internal_function_info {
404400
zend_uintptr_t required_num_args;
405401
zend_type type;
406-
zend_bool return_reference;
407-
zend_bool _is_variadic;
408402
} zend_internal_function_info;
409403

410404
struct _zend_op_array {
@@ -934,6 +928,14 @@ zend_string *zend_type_to_string(zend_type type);
934928
#define ZEND_SEND_BY_REF 1u
935929
#define ZEND_SEND_PREFER_REF 2u
936930

931+
/* The send mode and is_variadic flag are stored as part of zend_type */
932+
#define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT
933+
#define _ZEND_IS_VARIADIC_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 2))
934+
#define ZEND_ARG_SEND_MODE(arg_info) \
935+
((ZEND_TYPE_FULL_MASK((arg_info)->type) >> _ZEND_SEND_MODE_SHIFT) & 3)
936+
#define ZEND_ARG_IS_VARIADIC(arg_info) \
937+
((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_VARIADIC_BIT) != 0)
938+
937939
#define ZEND_DIM_IS (1 << 0) /* isset fetch needed for null coalesce */
938940
#define ZEND_DIM_ALTERNATIVE_SYNTAX (1 << 1) /* deprecated curly brace usage */
939941

@@ -950,7 +952,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
950952
}
951953
arg_num = zf->common.num_args;
952954
}
953-
return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0);
955+
return UNEXPECTED((ZEND_ARG_SEND_MODE(&zf->common.arg_info[arg_num]) & mask) != 0);
954956
}
955957

956958
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \

0 commit comments

Comments
 (0)