Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit be0132e

Browse files
committed
Remove cache slot from ZEND_VERIFY_TYPE and arg RECV opcodes
1 parent bd43334 commit be0132e

File tree

10 files changed

+57
-190
lines changed

10 files changed

+57
-190
lines changed

‎UPGRADING.INTERNALS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES
2525
char* instead of zend_string*-based smart strings.
2626
. Added php_build_provider() to retrieve the value of PHP_BUILD_PROVIDER at
2727
runtime.
28+
. Removed the cache_slot argument of zend_check_user_type_slow() because
29+
now it only relies on the CE cache.
2830

2931
========================
3032
2. Build system changes

‎Zend/Optimizer/compact_literals.c

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -43,50 +43,6 @@ typedef struct _literal_info {
4343
info[n].num_related = (related); \
4444
} while (0)
4545

46-
static size_t type_num_classes(const zend_op_array *op_array, uint32_t arg_num)
47-
{
48-
zend_arg_info *arg_info;
49-
if (arg_num > 0) {
50-
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
51-
return 0;
52-
}
53-
if (EXPECTED(arg_num <= op_array->num_args)) {
54-
arg_info = &op_array->arg_info[arg_num-1];
55-
} else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
56-
arg_info = &op_array->arg_info[op_array->num_args];
57-
} else {
58-
return 0;
59-
}
60-
} else {
61-
arg_info = op_array->arg_info - 1;
62-
}
63-
64-
if (ZEND_TYPE_IS_COMPLEX(arg_info->type)) {
65-
if (ZEND_TYPE_HAS_LIST(arg_info->type)) {
66-
/* Intersection types cannot have nested list types */
67-
if (ZEND_TYPE_IS_INTERSECTION(arg_info->type)) {
68-
return ZEND_TYPE_LIST(arg_info->type)->num_types;
69-
}
70-
ZEND_ASSERT(ZEND_TYPE_IS_UNION(arg_info->type));
71-
size_t count = 0;
72-
const zend_type *list_type;
73-
74-
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) {
75-
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
76-
count += ZEND_TYPE_LIST(*list_type)->num_types;
77-
} else {
78-
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
79-
count += 1;
80-
}
81-
} ZEND_TYPE_LIST_FOREACH_END();
82-
return count;
83-
}
84-
return 1;
85-
}
86-
87-
return 0;
88-
}
89-
9046
static uint32_t add_static_slot(HashTable *hash,
9147
zend_op_array *op_array,
9248
uint32_t op1,
@@ -504,26 +460,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
504460
opline->op2.constant = map[opline->op2.constant];
505461
}
506462
switch (opline->opcode) {
507-
case ZEND_RECV_INIT:
508-
case ZEND_RECV:
509-
case ZEND_RECV_VARIADIC:
510-
{
511-
size_t num_classes = type_num_classes(op_array, opline->op1.num);
512-
if (num_classes) {
513-
opline->extended_value = cache_size;
514-
cache_size += num_classes * sizeof(void *);
515-
}
516-
break;
517-
}
518-
case ZEND_VERIFY_RETURN_TYPE:
519-
{
520-
size_t num_classes = type_num_classes(op_array, 0);
521-
if (num_classes) {
522-
opline->op2.num = cache_size;
523-
cache_size += num_classes * sizeof(void *);
524-
}
525-
break;
526-
}
527463
case ZEND_ASSIGN_STATIC_PROP_OP:
528464
if (opline->op1_type == IS_CONST) {
529465
// op1 static property

‎Zend/zend_compile.c

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,33 +2620,6 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
26202620
}
26212621
/* }}} */
26222622

2623-
/* Remember to update type_num_classes() in compact_literals.c when changing this function */
2624-
static size_t zend_type_get_num_classes(const zend_type type) {
2625-
if (!ZEND_TYPE_IS_COMPLEX(type)) {
2626-
return 0;
2627-
}
2628-
if (ZEND_TYPE_HAS_LIST(type)) {
2629-
/* Intersection types cannot have nested list types */
2630-
if (ZEND_TYPE_IS_INTERSECTION(type)) {
2631-
return ZEND_TYPE_LIST(type)->num_types;
2632-
}
2633-
ZEND_ASSERT(ZEND_TYPE_IS_UNION(type));
2634-
size_t count = 0;
2635-
const zend_type *list_type;
2636-
2637-
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
2638-
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
2639-
count += ZEND_TYPE_LIST(*list_type)->num_types;
2640-
} else {
2641-
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
2642-
count += 1;
2643-
}
2644-
} ZEND_TYPE_LIST_FOREACH_END();
2645-
return count;
2646-
}
2647-
return 1;
2648-
}
2649-
26502623
static void zend_emit_return_type_check(
26512624
znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */
26522625
{
@@ -2708,8 +2681,6 @@ static void zend_emit_return_type_check(
27082681
opline->result_type = expr->op_type = IS_TMP_VAR;
27092682
opline->result.var = expr->u.op.var = get_temporary_variable();
27102683
}
2711-
2712-
opline->op2.num = zend_alloc_cache_slots(zend_type_get_num_classes(return_info->type));
27132684
}
27142685
}
27152686
/* }}} */
@@ -7754,12 +7725,6 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
77547725
SET_NODE(opline->result, &var_node);
77557726
opline->op1.num = i + 1;
77567727

7757-
if (type_ast) {
7758-
/* Allocate cache slot to speed-up run-time class resolution */
7759-
opline->extended_value =
7760-
zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type));
7761-
}
7762-
77637728
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
77647729
| (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
77657730
ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;

‎Zend/zend_execute.c

Lines changed: 26 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,23 +1099,9 @@ static zend_always_inline bool zend_value_instanceof_static(const zval *zv) {
10991099
return instanceof_function(Z_OBJCE_P(zv), called_scope);
11001100
}
11011101

1102-
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
1103-
* internal functions is enabled. Avoid unnecessary checks in release builds. */
1104-
#if ZEND_DEBUG
1105-
# define HAVE_CACHE_SLOT (cache_slot != NULL)
1106-
#else
1107-
# define HAVE_CACHE_SLOT 1
1108-
#endif
1109-
1110-
#define PROGRESS_CACHE_SLOT() if (HAVE_CACHE_SLOT) {cache_slot++;}
1111-
1112-
static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot(
1113-
void **cache_slot, const zend_type *type)
1102+
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
1103+
const zend_type *type)
11141104
{
1115-
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1116-
return (zend_class_entry *) *cache_slot;
1117-
}
1118-
11191105
zend_string *name = ZEND_TYPE_NAME(*type);
11201106
zend_class_entry *ce;
11211107
if (ZSTR_HAS_CE_CACHE(name)) {
@@ -1134,68 +1120,54 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot(
11341120
return NULL;
11351121
}
11361122
}
1137-
if (HAVE_CACHE_SLOT) {
1138-
*cache_slot = (void *) ce;
1139-
}
11401123
return ce;
11411124
}
11421125

1143-
static bool zend_check_intersection_type_from_cache_slot(
1126+
static bool zend_check_intersection_type_from_list(
11441127
const zend_type_list *intersection_type_list,
1145-
const zend_class_entry *arg_ce,
1146-
void ***cache_slot_ptr)
1128+
zend_class_entry *arg_ce)
11471129
{
1148-
void**cache_slot=*cache_slot_ptr;
1130+
zend_class_entry*ce;
11491131
const zend_type *list_type;
1150-
bool status = true;
11511132
ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
1152-
/* Only check classes if the type might be valid */
1153-
if (status) {
1154-
zend_class_entry *ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1155-
/* If type is not an instance of one of the types taking part in the
1156-
* intersection it cannot be a valid instance of the whole intersection type. */
1157-
if (!ce || !instanceof_function(arg_ce, ce)) {
1158-
status = false;
1159-
}
1133+
ce = zend_fetch_ce_from_type(list_type);
1134+
/* If type is not an instance of one of the types taking part in the
1135+
* intersection it cannot be a valid instance of the whole intersection type. */
1136+
if (!ce || !instanceof_function(arg_ce, ce)) {
1137+
return false;
11601138
}
1161-
PROGRESS_CACHE_SLOT();
11621139
} ZEND_TYPE_LIST_FOREACH_END();
1163-
if (HAVE_CACHE_SLOT) {
1164-
*cache_slot_ptr = cache_slot;
1165-
}
1166-
return status;
1140+
return true;
11671141
}
11681142

11691143
static zend_always_inline bool zend_check_type_slow(
1170-
const zend_type *type, zval *arg, const zend_reference *ref,void**cache_slot,
1144+
const zend_type *type, zval *arg, const zend_reference *ref,
11711145
bool is_return_type, bool is_internal)
11721146
{
11731147
if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
11741148
zend_class_entry *ce;
11751149
if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) {
11761150
if (ZEND_TYPE_IS_INTERSECTION(*type)) {
1177-
return zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg), &cache_slot);
1151+
return zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg));
11781152
} else {
11791153
const zend_type *list_type;
11801154
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
11811155
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1182-
if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), &cache_slot)) {
1156+
if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) {
11831157
return true;
11841158
}
1185-
/* The cache_slot is progressed in zend_check_intersection_type_from_cache_slot() */
11861159
} else {
11871160
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1188-
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1161+
ce = zend_fetch_ce_from_type(list_type);
11891162
/* Instance of a single type part of a union is sufficient to pass the type check */
11901163
if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
11911164
return true;
11921165
}
1193-
PROGRESS_CACHE_SLOT();
11941166
}
11951167
} ZEND_TYPE_LIST_FOREACH_END();
11961168
}
11971169
} else {
1198-
ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1170+
ce = zend_fetch_ce_from_type(type);
11991171
/* If we have a CE we check if it satisfies the type constraint,
12001172
* otherwise it will check if a standard type satisfies it. */
12011173
if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
@@ -1232,7 +1204,7 @@ static zend_always_inline bool zend_check_type_slow(
12321204
}
12331205

12341206
static zend_always_inline bool zend_check_type(
1235-
const zend_type *type, zval *arg, void**cache_slot, zend_class_entry *scope,
1207+
const zend_type *type, zval *arg, zend_class_entry *scope,
12361208
bool is_return_type, bool is_internal)
12371209
{
12381210
const zend_reference *ref = NULL;
@@ -1247,25 +1219,25 @@ static zend_always_inline bool zend_check_type(
12471219
return 1;
12481220
}
12491221

1250-
return zend_check_type_slow(type, arg, ref, cache_slot, is_return_type, is_internal);
1222+
return zend_check_type_slow(type, arg, ref, is_return_type, is_internal);
12511223
}
12521224

12531225
ZEND_API bool zend_check_user_type_slow(
1254-
const zend_type *type, zval *arg, const zend_reference *ref, void**cache_slot, bool is_return_type)
1226+
const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type)
12551227
{
12561228
return zend_check_type_slow(
1257-
type, arg, ref, cache_slot, is_return_type, /* is_internal */ false);
1229+
type, arg, ref, is_return_type, /* is_internal */ false);
12581230
}
12591231

1260-
static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg, void**cache_slot)
1232+
static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg)
12611233
{
12621234
const zend_arg_info *cur_arg_info;
12631235

12641236
ZEND_ASSERT(arg_num <= zf->common.num_args);
12651237
cur_arg_info = &zf->common.arg_info[arg_num-1];
12661238

12671239
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1268-
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1240+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, 0, 0))) {
12691241
zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
12701242
return 0;
12711243
}
@@ -1274,10 +1246,10 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf
12741246
}
12751247

12761248
static zend_always_inline bool zend_verify_variadic_arg_type(
1277-
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void**cache_slot)
1249+
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg)
12781250
{
12791251
ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
1280-
if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1252+
if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, 0, 0))) {
12811253
zend_verify_arg_error(zf, arg_info, arg_num, arg);
12821254
return 0;
12831255
}
@@ -1302,7 +1274,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
13021274
}
13031275

13041276
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1305-
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
1277+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, 0, /* is_internal */ 1))) {
13061278
return 0;
13071279
}
13081280
arg++;
@@ -1508,7 +1480,7 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re
15081480
return 1;
15091481
}
15101482

1511-
if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */NULL, NULL, 1, /* is_internal */ 1))) {
1483+
if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, 1, /* is_internal */ 1))) {
15121484
zend_verify_internal_return_error(zf, ret);
15131485
return 0;
15141486
}

‎Zend/zend_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ ZEND_API ZEND_COLD void zend_verify_never_error(
106106
const zend_function *zf);
107107
ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref);
108108
ZEND_API bool zend_check_user_type_slow(
109-
const zend_type *type, zval *arg, const zend_reference *ref, void**cache_slot, bool is_return_type);
109+
const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type);
110110

111111
#if ZEND_DEBUG
112112
ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /