Skip to content

Commit de02cc3

Browse files
committed
Store pass_by_reference+is_variadic in type mask
1 parent 9f44caa commit de02cc3

23 files changed

+159
-138
lines changed

Zend/zend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ static void zend_resolve_property_types(void) /* {{{ */
965965
zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name);
966966

967967
ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS);
968-
prop_info->type = (zend_type) ZEND_TYPE_INIT_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);
969969
zend_string_release(lc_type_name);
970970
zend_string_release(type_name);
971971
}

Zend/zend_API.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,10 +2052,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
20522052
} else {
20532053
internal_function->required_num_args = info->required_num_args;
20542054
}
2055-
if (info->return_reference) {
2055+
if (ZEND_ARG_SEND_MODE(info)) {
20562056
internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
20572057
}
2058-
if (ptr->arg_info[ptr->num_args].is_variadic) {
2058+
if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
20592059
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
20602060
/* Don't count the variadic argument */
20612061
internal_function->num_args--;
@@ -3708,7 +3708,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze
37083708

37093709
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
37103710
{
3711-
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE());
3711+
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
37123712
}
37133713
/* }}} */
37143714

Zend/zend_API.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,43 @@ 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, ZEND_TYPE_INIT_NONE(), pass_by_ref, 0},
100-
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 },
101-
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
102-
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
103-
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 0 },
104-
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, ZEND_TYPE_INIT_NONE(), pass_by_ref, 1 },
105-
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 1 },
106-
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_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)) },
107118

108119
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
109120
static const zend_internal_arg_info name[] = { \
110-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_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)) },
111123

112124
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
113125
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
114126

115127
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
116128
static const zend_internal_arg_info name[] = { \
117-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_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)) },
118130
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
119131
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
120132

121133
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
122134
static const zend_internal_arg_info name[] = { \
123-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(), return_reference, 0 },
135+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)) },
124136
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
125137
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
126138
#define ZEND_END_ARG_INFO() };

Zend/zend_closures.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,16 +547,16 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp)
547547
if (arg_info->name) {
548548
if (zstr_args) {
549549
name = zend_strpprintf(0, "%s$%s",
550-
arg_info->pass_by_reference ? "&" : "",
550+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
551551
ZSTR_VAL(arg_info->name));
552552
} else {
553553
name = zend_strpprintf(0, "%s$%s",
554-
arg_info->pass_by_reference ? "&" : "",
554+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
555555
((zend_internal_arg_info*)arg_info)->name);
556556
}
557557
} else {
558558
name = zend_strpprintf(0, "%s$param%d",
559-
arg_info->pass_by_reference ? "&" : "",
559+
ZEND_ARG_SEND_MODE(arg_info) ? "&" : "",
560560
i + 1);
561561
}
562562
ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));

Zend/zend_compile.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
10961096
} else if (ZEND_TYPE_IS_CE(type)) {
10971097
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
10981098
} else {
1099-
uint32_t type_mask = ZEND_TYPE_MASK_WITHOUT_NULL(type);
1099+
uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type);
11001100
switch (type_mask) {
11011101
case MAY_BE_FALSE|MAY_BE_TRUE:
11021102
str = ZSTR_KNOWN(ZEND_STR_BOOL);
@@ -1160,7 +1160,7 @@ static void zend_mark_function_as_generator() /* {{{ */
11601160
|| zend_string_equals_literal_ci(name, "Iterator")
11611161
|| zend_string_equals_literal_ci(name, "Generator");
11621162
} else {
1163-
valid_type = (ZEND_TYPE_MASK(return_info.type) & MAY_BE_ITERABLE) != 0;
1163+
valid_type = (ZEND_TYPE_FULL_MASK(return_info.type) & MAY_BE_ITERABLE) != 0;
11641164
}
11651165

11661166
if (!valid_type) {
@@ -5288,11 +5288,11 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
52885288
n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
52895289
i = 0;
52905290
while (i < n) {
5291-
ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference);
5291+
ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i]));
52925292
i++;
52935293
}
5294-
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) {
5295-
uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference;
5294+
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) {
5295+
uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]);
52965296
while (i < MAX_ARG_FLAG_NUM) {
52975297
ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
52985298
i++;
@@ -5311,7 +5311,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53115311
}
53125312

53135313
if (ast->kind == ZEND_AST_TYPE) {
5314-
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null);
5314+
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null, 0);
53155315
} else {
53165316
zend_string *class_name = zend_ast_get_str(ast);
53175317
zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
@@ -5325,7 +5325,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53255325
if (type == IS_VOID && allow_null) {
53265326
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
53275327
}
5328-
return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null);
5328+
return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null, 0);
53295329
} else {
53305330
uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
53315331
if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
@@ -5336,7 +5336,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53365336
zend_string_addref(class_name);
53375337
}
53385338

5339-
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null);
5339+
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null, 0);
53405340
}
53415341
}
53425342
}
@@ -5355,11 +5355,11 @@ static zend_bool zend_is_valid_default_value(zend_type type, zval *value)
53555355
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
53565356
return 1;
53575357
}
5358-
if ((ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
5358+
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
53595359
/* Integers are allowed as initializers for floating-point values. */
53605360
return 1;
53615361
}
5362-
if ((ZEND_TYPE_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
5362+
if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
53635363
return 1;
53645364
}
53655365
return 0;
@@ -5376,9 +5376,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
53765376
/* Use op_array->arg_info[-1] for return type */
53775377
arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
53785378
arg_infos->name = NULL;
5379-
arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
5380-
arg_infos->is_variadic = 0;
53815379
arg_infos->type = zend_compile_typename(return_type_ast, 0);
5380+
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
5381+
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
53825382
arg_infos++;
53835383
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
53845384
} else {
@@ -5450,23 +5450,18 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
54505450

54515451
arg_info = &arg_infos[i];
54525452
arg_info->name = zend_string_copy(name);
5453-
arg_info->pass_by_reference = is_ref;
5454-
arg_info->is_variadic = is_variadic;
5455-
arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE();
5453+
arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0);
54565454

54575455
if (type_ast) {
54585456
uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
54595457

5460-
uint32_t arg_type;
54615458
zend_bool is_class;
54625459

54635460
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
54645461
arg_info->type = zend_compile_typename(type_ast, default_type == IS_NULL);
5465-
54665462
is_class = ZEND_TYPE_IS_CLASS(arg_info->type);
5467-
arg_type = !is_class ? ZEND_TYPE_MASK(arg_info->type) : 0;
54685463

5469-
if (arg_type & MAY_BE_VOID) {
5464+
if (!is_class && (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID)) {
54705465
zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
54715466
}
54725467

@@ -5484,6 +5479,8 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
54845479
opline->extended_value = zend_alloc_cache_slot();
54855480
}
54865481
}
5482+
5483+
ZEND_TYPE_FULL_MASK(arg_info->type) |= _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic);
54875484
}
54885485

54895486
/* These are assigned at the end to avoid uninitialized memory in case of an error */
@@ -5983,12 +5980,12 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /
59835980
zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
59845981
zend_string *doc_comment = NULL;
59855982
zval value_zv;
5986-
zend_type type = ZEND_TYPE_INIT_NONE();
5983+
zend_type type = ZEND_TYPE_INIT_NONE(0);
59875984

59885985
if (type_ast) {
59895986
type = zend_compile_typename(type_ast, 0);
59905987

5991-
if (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
5988+
if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
59925989
zend_string *str = zend_type_to_string(type);
59935990
zend_error_noreturn(E_COMPILE_ERROR,
59945991
"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 {
@@ -931,6 +925,14 @@ zend_string *zend_type_to_string(zend_type type);
931925
#define ZEND_SEND_BY_REF 1u
932926
#define ZEND_SEND_PREFER_REF 2u
933927

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

@@ -947,7 +949,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
947949
}
948950
arg_num = zf->common.num_args;
949951
}
950-
return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0);
952+
return UNEXPECTED((ZEND_ARG_SEND_MODE(&zf->common.arg_info[arg_num]) & mask) != 0);
951953
}
952954

953955
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \

0 commit comments

Comments
 (0)